diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-02-22 15:00:15 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-02-22 15:00:15 +0300 |
commit | cd0d335183c8aa2c947a68ed6d5ded02a3cf2d2a (patch) | |
tree | fa56926998346499ade8504ec295fea08117da83 /source/blender/draw/intern | |
parent | 48aeb0b64008a947c5165d45d4a78f142f70e84c (diff) |
Clay Engine: Started Armature drawing
This should give the overall direction to whom wants to finish it.
- Renamed EDIT mode engine to EDIT_MESH mode engine
- Introduce EDIT_ARMATURE mode engine
- Started to port legacy drawarmature.c to draw_armature.c
Diffstat (limited to 'source/blender/draw/intern')
-rw-r--r-- | source/blender/draw/intern/draw_armature.c | 323 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.c | 378 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.h | 7 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 28 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_mode_pass.c | 151 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_mode_pass.h | 19 |
6 files changed, 825 insertions, 81 deletions
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c new file mode 100644 index 00000000000..68d1b3d7ea4 --- /dev/null +++ b/source/blender/draw/intern/draw_armature.c @@ -0,0 +1,323 @@ +/* + * Copyright 2016, Blender Foundation. + * + * 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_armature.c + * \ingroup draw + */ + +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "DNA_anim_types.h" +#include "DNA_armature_types.h" +#include "DNA_constraint_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_view3d_types.h" +#include "DNA_object_types.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_dlrbTree.h" +#include "BLI_utildefines.h" + +#include "BKE_animsys.h" +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_global.h" +#include "BKE_modifier.h" +#include "BKE_nla.h" +#include "BKE_curve.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "ED_armature.h" +#include "ED_keyframes_draw.h" + +#include "UI_resources.h" + +#include "draw_mode_pass.h" + +#define BONE_VAR(eBone, pchan, var) ((eBone) ? (eBone->var) : (pchan->var)) +#define BONE_FLAG(eBone, pchan) ((eBone) ? (eBone->flag) : (pchan->bone->flag)) + +/* *************** Armature Drawing - Coloring API ***************************** */ + +static float colorBoneSolid[4]; +static float colorTextHi[4]; +static float colorText[4]; +static float colorVertexSelect[4]; +static float colorVertex[4]; + +static const float *constColor; + +static void update_color(const float const_color[4]) +{ + constColor = const_color; + + UI_GetThemeColor4fv(TH_BONE_SOLID, colorBoneSolid); + UI_GetThemeColor4fv(TH_TEXT_HI, colorTextHi); + UI_GetThemeColor4fv(TH_TEXT, colorText); + UI_GetThemeColor4fv(TH_VERTEX_SELECT, colorVertexSelect); + UI_GetThemeColor4fv(TH_VERTEX, colorVertex); +} + +static const float *get_bone_solid_color(EditBone *eBone, bPoseChannel *pchan, bArmature *arm) +{ + if (constColor) + return colorBoneSolid; + + /* Edit Mode */ + if (eBone) { + if (eBone->flag & BONE_SELECTED) + return colorVertexSelect; + } + + return colorBoneSolid; +} + +static const float *get_bone_wire_color(EditBone *eBone, bPoseChannel *pchan, bArmature *arm) +{ + if (constColor) + return constColor; + + if (eBone) { + if (eBone->flag & BONE_SELECTED) + return colorVertexSelect; + } + + return colorVertex; +} + +/* *************** Armature drawing, helper calls for parts ******************* */ + +static void draw_bone_update_disp_matrix(EditBone *eBone, bPoseChannel *pchan, int drawtype) +{ + float s[4][4], ebmat[4][4]; + float length; + float (*bone_mat)[4]; + float (*disp_mat)[4]; + float (*disp_tail_mat)[4]; + + /* TODO : This should be moved to depsgraph or armature refresh + * and not be tight to the draw pass creation. + * This would refresh armature without invalidating the draw cache */ + if (pchan) { + length = pchan->bone->length; + bone_mat = pchan->pose_mat; + disp_mat = pchan->disp_mat; + disp_tail_mat = pchan->disp_tail_mat; + } + else { + eBone->length = len_v3v3(eBone->tail, eBone->head); + ED_armature_ebone_to_mat4(eBone, ebmat); + + length = eBone->length; + bone_mat = ebmat; + disp_mat = eBone->disp_mat; + disp_tail_mat = eBone->disp_tail_mat; + } + + if (pchan && pchan->custom) { + /* TODO */ + } + else if (drawtype == ARM_ENVELOPE) { + /* TODO */ + } + else if (drawtype == ARM_LINE) { + /* TODO */ + } + else if (drawtype == ARM_WIRE) { + /* TODO */ + } + else if (drawtype == ARM_B_BONE) { + /* TODO */ + } + else { + scale_m4_fl(s, length); + mul_m4_m4m4(disp_mat, bone_mat, s); + copy_m4_m4(disp_tail_mat, disp_mat); + translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f); + } +} + +static void draw_axes(EditBone *eBone, bPoseChannel *pchan) +{ + const float *col = (constColor) ? constColor : + (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? colorTextHi : colorText; + + DRW_shgroup_bone_axes(BONE_VAR(eBone, pchan, disp_tail_mat), col); +} + +static void draw_points(EditBone *eBone, bPoseChannel *pchan, bArmature *arm) +{ + const float *col_solid_root = colorBoneSolid; + const float *col_solid_tail = colorBoneSolid; + const float *col_wire_root = (constColor) ? constColor : colorVertex; + const float *col_wire_tail = (constColor) ? constColor : colorVertex; + + /* Edit bone points can be selected */ + if (eBone) { + if (eBone->flag & BONE_ROOTSEL) { + col_solid_root = colorVertexSelect; + col_wire_root = colorVertexSelect; + } + if (eBone->flag & BONE_TIPSEL) { + col_solid_tail = colorVertexSelect; + col_wire_tail = colorVertexSelect; + } + } + + /* Draw root point if we are not connected and parent are not hidden */ + if ((BONE_FLAG(eBone, pchan) & BONE_CONNECTED) == 0) { + if (eBone) { + if (!((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent))) { + DRW_shgroup_bone_point_solid(eBone->disp_mat, col_solid_root); + DRW_shgroup_bone_point_wire(eBone->disp_mat, col_wire_root); + } + } + else { + Bone *bone = pchan->bone; + if (!((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))) { + DRW_shgroup_bone_point_solid(pchan->disp_mat, col_solid_root); + DRW_shgroup_bone_point_wire(pchan->disp_mat, col_wire_root); + } + } + } + + /* Draw tip point */ + DRW_shgroup_bone_point_solid(BONE_VAR(eBone, pchan, disp_tail_mat), col_solid_tail); + DRW_shgroup_bone_point_wire(BONE_VAR(eBone, pchan, disp_tail_mat), col_wire_tail); +} + +static void draw_bone_custom_shape(EditBone *eBone, bPoseChannel *pchan, bArmature *arm) +{ +} + +static void draw_bone_envelope(EditBone *eBone, bPoseChannel *pchan, bArmature *arm) +{ +} + +static void draw_bone_line(EditBone *eBone, bPoseChannel *pchan, bArmature *arm) +{ +} + +static void draw_bone_wire(EditBone *eBone, bPoseChannel *pchan, bArmature *arm) +{ +} + +static void draw_bone_box(EditBone *eBone, bPoseChannel *pchan, bArmature *arm) +{ +} + +static void draw_bone_octahedral(EditBone *eBone, bPoseChannel *pchan, bArmature *arm) +{ + const float *col_solid = get_bone_solid_color(eBone, pchan, arm); + const float *col_wire = get_bone_wire_color(eBone, pchan, arm); + + DRW_shgroup_bone_octahedral_solid(BONE_VAR(eBone, pchan, disp_mat), col_solid); + DRW_shgroup_bone_octahedral_wire(BONE_VAR(eBone, pchan, disp_mat), col_wire); + + draw_points(eBone, pchan, arm); +} + +void draw_armature_edit(Object *ob) +{ + EditBone *eBone; + bArmature *arm = ob->data; + unsigned int index; + + update_color(NULL); + + for (eBone = arm->edbo->first, index = 0; eBone; eBone = eBone->next, index++) { + if (eBone->layer & arm->layer) { + if ((eBone->flag & BONE_HIDDEN_A) == 0) { + + draw_bone_update_disp_matrix(eBone, NULL, arm->drawtype); + + if (arm->drawtype == ARM_ENVELOPE) + draw_bone_envelope(eBone, NULL, arm); + else if (arm->drawtype == ARM_LINE) + draw_bone_line(eBone, NULL, arm); + else if (arm->drawtype == ARM_WIRE) + draw_bone_wire(eBone, NULL, arm); + else if (arm->drawtype == ARM_B_BONE) + draw_bone_box(eBone, NULL, arm); + else + draw_bone_octahedral(eBone, NULL, arm); + + /* Draw additional axes */ + if (arm->flag & ARM_DRAWAXES) + draw_axes(eBone, NULL); + } + } + } +} + +/* if const_color is NULL do pose mode coloring */ +void draw_armature_pose(Object *ob, const float const_color[4]) +{ + bArmature *arm = ob->data; + bPoseChannel *pchan; + Bone *bone; + + update_color(const_color); + + /* We can't safely draw non-updated pose, might contain NULL bone pointers... */ + if (ob->pose->flag & POSE_RECALC) { + BKE_pose_rebuild(ob, arm); + } + + /* being set below */ + arm->layer_used = 0; + + for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + bone = pchan->bone; + arm->layer_used |= bone->layer; + + /* bone must be visible */ + if ((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) { + if (bone->layer & arm->layer) { + + draw_bone_update_disp_matrix(NULL, pchan, arm->drawtype); + + if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) + draw_bone_custom_shape(NULL, pchan, arm); + else if (arm->drawtype == ARM_ENVELOPE) + draw_bone_envelope(NULL, pchan, arm); + else if (arm->drawtype == ARM_LINE) + draw_bone_line(NULL, pchan, arm); + else if (arm->drawtype == ARM_WIRE) + draw_bone_wire(NULL, pchan, arm); + else if (arm->drawtype == ARM_B_BONE) + draw_bone_box(NULL, pchan, arm); + else + draw_bone_octahedral(NULL, pchan, arm); + + /* Draw additional axes */ + if (arm->flag & ARM_DRAWAXES) + draw_axes(NULL, pchan); + } + } + } +}
\ No newline at end of file diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 55c07304ec2..8f30f8936d0 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -52,6 +52,11 @@ static struct DRWShapeCache{ Batch *drw_lamp; Batch *drw_lamp_sunrays; Batch *drw_speaker; + Batch *drw_bone_octahedral; + Batch *drw_bone_octahedral_wire; + Batch *drw_bone_point; + Batch *drw_bone_point_wire; + Batch *drw_bone_arrows; } SHC = {NULL}; void DRW_shape_cache_free(void) @@ -84,6 +89,135 @@ void DRW_shape_cache_free(void) Batch_discard_all(SHC.drw_lamp_sunrays); if (SHC.drw_speaker) Batch_discard_all(SHC.drw_speaker); + if (SHC.drw_bone_octahedral) + Batch_discard_all(SHC.drw_bone_octahedral); + if (SHC.drw_bone_octahedral_wire) + Batch_discard_all(SHC.drw_bone_octahedral_wire); + if (SHC.drw_bone_point) + Batch_discard_all(SHC.drw_bone_point); + if (SHC.drw_bone_point_wire) + Batch_discard_all(SHC.drw_bone_point_wire); + if (SHC.drw_bone_arrows) + Batch_discard_all(SHC.drw_bone_arrows); +} + +/* Helper functions */ + +static void add_fancy_edge(VertexBuffer *vbo, unsigned int pos_id, unsigned int n1_id, unsigned int n2_id, + unsigned int *v_idx, const float co1[3], const float co2[3], + const float n1[3], const float n2[3]) +{ + setAttrib(vbo, n1_id, *v_idx, n1); + setAttrib(vbo, n2_id, *v_idx, n2); + setAttrib(vbo, pos_id, (*v_idx)++, co1); + + setAttrib(vbo, n1_id, *v_idx, n1); + setAttrib(vbo, n2_id, *v_idx, n2); + setAttrib(vbo, pos_id, (*v_idx)++, co2); +} + +static void add_lat_lon_vert(VertexBuffer *vbo, unsigned int pos_id, unsigned int nor_id, + unsigned int *v_idx, const float rad, const float lat, const float lon) +{ + float pos[3], nor[3]; + nor[0] = sinf(lat) * cosf(lon); + nor[1] = cosf(lat); + nor[2] = sinf(lat) * sinf(lon); + mul_v3_v3fl(pos, nor, rad); + + setAttrib(vbo, nor_id, *v_idx, nor); + setAttrib(vbo, pos_id, (*v_idx)++, pos); +} + +static VertexBuffer *fill_arrows_vbo(const float scale) +{ + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + /* Line */ + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 6 * 3); + + float v1[3] = {0.0, 0.0, 0.0}; + float v2[3] = {0.0, 0.0, 0.0}; + float vtmp1[3], vtmp2[3]; + + for (int axis = 0; axis < 3; axis++) { + const int arrow_axis = (axis == 0) ? 1 : 0; + + v2[axis] = 1.0f; + mul_v3_v3fl(vtmp1, v1, scale); + mul_v3_v3fl(vtmp2, v2, scale); + setAttrib(vbo, pos_id, axis * 6 + 0, vtmp1); + setAttrib(vbo, pos_id, axis * 6 + 1, vtmp2); + + v1[axis] = 0.85f; + v1[arrow_axis] = -0.08f; + mul_v3_v3fl(vtmp1, v1, scale); + mul_v3_v3fl(vtmp2, v2, scale); + setAttrib(vbo, pos_id, axis * 6 + 2, vtmp1); + setAttrib(vbo, pos_id, axis * 6 + 3, vtmp2); + + v1[arrow_axis] = 0.08f; + mul_v3_v3fl(vtmp1, v1, scale); + mul_v3_v3fl(vtmp2, v2, scale); + setAttrib(vbo, pos_id, axis * 6 + 4, vtmp1); + setAttrib(vbo, pos_id, axis * 6 + 5, vtmp2); + + /* reset v1 & v2 to zero */ + v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f; + } + + return vbo; +} + +static VertexBuffer *sphere_wire_vbo(const float rad) +{ +#define NSEGMENTS 16 + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, NSEGMENTS * 2 * 3); + + /* a single ring of vertices */ + float p[NSEGMENTS][2]; + for (int i = 0; i < NSEGMENTS; ++i) { + float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); + p[i][0] = rad * cosf(angle); + p[i][1] = rad * sinf(angle); + } + + for (int axis = 0; axis < 3; ++axis) { + for (int i = 0; i < NSEGMENTS; ++i) { + for (int j = 0; j < 2; ++j) { + float cv[2], v[3]; + + cv[0] = p[(i+j) % NSEGMENTS][0]; + cv[1] = p[(i+j) % NSEGMENTS][1]; + + if (axis == 0) + v[0] = cv[0], v[1] = cv[1], v[2] = 0.0f; + else if (axis == 1) + v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1]; + else + v[0] = 0.0f, v[1] = cv[0], v[2] = cv[1]; + + setAttrib(vbo, pos_id, i*2 + j + (NSEGMENTS * 2 * axis), v); + } + } + } + + return vbo; +#undef NSEGMENTS } /* Quads */ @@ -290,50 +424,11 @@ Batch *DRW_cache_single_arrow_get(void) Batch *DRW_cache_empty_sphere_get(void) { -#define NSEGMENTS 16 if (!SHC.drw_empty_sphere) { - /* a single ring of vertices */ - float p[NSEGMENTS][2]; - for (int i = 0; i < NSEGMENTS; ++i) { - float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); - p[i][0] = cosf(angle); - p[i][1] = sinf(angle); - } - - /* Position Only 3D format */ - static VertexFormat format = { 0 }; - static unsigned pos_id; - if (format.attrib_ct == 0) { - pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); - } - - VertexBuffer *vbo = VertexBuffer_create_with_format(&format); - VertexBuffer_allocate_data(vbo, NSEGMENTS * 2 * 3); - - for (int axis = 0; axis < 3; ++axis) { - for (int i = 0; i < NSEGMENTS; ++i) { - for (int j = 0; j < 2; ++j) { - float cv[2], v[3]; - - cv[0] = p[(i+j) % NSEGMENTS][0]; - cv[1] = p[(i+j) % NSEGMENTS][1]; - - if (axis == 0) - v[0] = cv[0], v[1] = cv[1], v[2] = 0.0f; - else if (axis == 1) - v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1]; - else - v[0] = 0.0f, v[1] = cv[0], v[2] = cv[1]; - - setAttrib(vbo, pos_id, i*2 + j + (NSEGMENTS * 2 * axis), v); - } - } - } - + VertexBuffer *vbo = sphere_wire_vbo(1.0f); SHC.drw_empty_sphere = Batch_create(GL_LINES, vbo, NULL); } return SHC.drw_empty_sphere; -#undef NSEGMENTS } Batch *DRW_cache_empty_cone_get(void) @@ -387,39 +482,7 @@ Batch *DRW_cache_empty_cone_get(void) Batch *DRW_cache_arrows_get(void) { if (!SHC.drw_arrows) { - float v1[3] = {0.0, 0.0, 0.0}; - float v2[3] = {0.0, 0.0, 0.0}; - - /* Position Only 3D format */ - static VertexFormat format = { 0 }; - static unsigned pos_id; - if (format.attrib_ct == 0) { - pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); - } - - /* Line */ - VertexBuffer *vbo = VertexBuffer_create_with_format(&format); - VertexBuffer_allocate_data(vbo, 6 * 3); - - for (int axis = 0; axis < 3; axis++) { - const int arrow_axis = (axis == 0) ? 1 : 0; - - v2[axis] = 1.0f; - setAttrib(vbo, pos_id, axis * 6 + 0, v1); - setAttrib(vbo, pos_id, axis * 6 + 1, v2); - - v1[axis] = 0.85f; - v1[arrow_axis] = -0.08f; - setAttrib(vbo, pos_id, axis * 6 + 2, v1); - setAttrib(vbo, pos_id, axis * 6 + 3, v2); - - v1[arrow_axis] = 0.08f; - setAttrib(vbo, pos_id, axis * 6 + 4, v1); - setAttrib(vbo, pos_id, axis * 6 + 5, v2); - - /* reset v1 & v2 to zero */ - v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f; - } + VertexBuffer *vbo = fill_arrows_vbo(1.0f); SHC.drw_arrows = Batch_create(GL_LINES, vbo, NULL); } @@ -609,6 +672,175 @@ Batch *DRW_cache_speaker_get(void) return SHC.drw_speaker; } +/* Armature bones */ +static const float bone_octahedral_verts[6][3] = { + { 0.0f, 0.0f, 0.0f}, + { 0.1f, 0.1f, 0.1f}, + { 0.1f, 0.1f, -0.1f}, + {-0.1f, 0.1f, -0.1f}, + {-0.1f, 0.1f, 0.1f}, + { 0.0f, 1.0f, 0.0f} +}; + +static const unsigned int bone_octahedral_wire[24] = { + 0, 1, 1, 5, 5, 3, 3, 0, + 0, 4, 4, 5, 5, 2, 2, 0, + 1, 2, 2, 3, 3, 4, 4, 1, +}; + +/* aligned with bone_octahedral_wire + * Contains adjacent normal index */ +static const unsigned int bone_octahedral_wire_adjacent_face[24] = { + 0, 3, 4, 7, 5, 6, 1, 2, + 2, 3, 6, 7, 4, 5, 0, 1, + 0, 4, 1, 5, 2, 6, 3, 7, +}; + +static const unsigned int bone_octahedral_solid_tris[8][3] = { + {2, 1, 0}, /* bottom */ + {3, 2, 0}, + {4, 3, 0}, + {1, 4, 0}, + + {5, 1, 2}, /* top */ + {5, 2, 3}, + {5, 3, 4}, + {5, 4, 1} +}; + +/* aligned with bone_octahedral_solid_tris */ +static const float bone_octahedral_solid_normals[8][3] = { + { M_SQRT1_2, -M_SQRT1_2, 0.00000000f}, + {-0.00000000f, -M_SQRT1_2, -M_SQRT1_2}, + {-M_SQRT1_2, -M_SQRT1_2, 0.00000000f}, + { 0.00000000f, -M_SQRT1_2, M_SQRT1_2}, + { 0.99388373f, 0.11043154f, -0.00000000f}, + { 0.00000000f, 0.11043154f, -0.99388373f}, + {-0.99388373f, 0.11043154f, 0.00000000f}, + { 0.00000000f, 0.11043154f, 0.99388373f} +}; + +Batch *DRW_cache_bone_octahedral_get(void) +{ + if (!SHC.drw_bone_octahedral) { + unsigned int v_idx = 0; + + static VertexFormat format = { 0 }; + static unsigned pos_id, nor_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + nor_id = add_attrib(&format, "nor", GL_FLOAT, 3, KEEP_FLOAT); + } + + /* Vertices */ + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 24); + + for (int i = 0; i < 8; i++) { + setAttrib(vbo, nor_id, v_idx, bone_octahedral_solid_normals[i]); + setAttrib(vbo, pos_id, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][0]]); + setAttrib(vbo, nor_id, v_idx, bone_octahedral_solid_normals[i]); + setAttrib(vbo, pos_id, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][1]]); + setAttrib(vbo, nor_id, v_idx, bone_octahedral_solid_normals[i]); + setAttrib(vbo, pos_id, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][2]]); + } + + SHC.drw_bone_octahedral = Batch_create(GL_TRIANGLES, vbo, NULL); + } + return SHC.drw_bone_octahedral; +} + +Batch *DRW_cache_bone_octahedral_wire_outline_get(void) +{ + if (!SHC.drw_bone_octahedral_wire) { + unsigned int v_idx = 0; + + static VertexFormat format = { 0 }; + static unsigned pos_id, n1_id, n2_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + n1_id = add_attrib(&format, "N1", COMP_F32, 3, KEEP_FLOAT); + n2_id = add_attrib(&format, "N2", COMP_F32, 3, KEEP_FLOAT); + } + + /* Vertices */ + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 12 * 2); + + for (int i = 0; i < 12; i++) { + const float *co1 = bone_octahedral_verts[bone_octahedral_wire[i*2]]; + const float *co2 = bone_octahedral_verts[bone_octahedral_wire[i*2+1]]; + const float *n1 = bone_octahedral_solid_normals[bone_octahedral_wire_adjacent_face[i*2]]; + const float *n2 = bone_octahedral_solid_normals[bone_octahedral_wire_adjacent_face[i*2+1]]; + add_fancy_edge(vbo, pos_id, n1_id, n2_id, &v_idx, co1, co2, n1, n2); + } + + SHC.drw_bone_octahedral_wire = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_bone_octahedral_wire; +} + +Batch *DRW_cache_bone_point_get(void) +{ + if (!SHC.drw_bone_point) { + const int lon_res = 16; + const int lat_res = 8; + const float rad = 0.05f; + const float lon_inc = 2 * M_PI / lon_res; + const float lat_inc = M_PI / lat_res; + unsigned int v_idx = 0; + + static VertexFormat format = { 0 }; + static unsigned pos_id, nor_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + nor_id = add_attrib(&format, "nor", GL_FLOAT, 3, KEEP_FLOAT); + } + + /* Vertices */ + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, (lat_res-1) * lon_res * 6); + + float lon = 0.0f; + for(int i = 0; i < lon_res; i++, lon += lon_inc) { + float lat = 0.0f; + for(int j = 0; j < lat_res; j++, lat += lat_inc) { + if (j != lat_res - 1) { /* Pole */ + add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat+lat_inc, lon+lon_inc); + add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat+lat_inc, lon); + add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat, lon); + } + + if (j != 0) { /* Pole */ + add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat, lon+lon_inc); + add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat+lat_inc, lon+lon_inc); + add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat, lon); + } + } + } + + SHC.drw_bone_point = Batch_create(GL_TRIANGLES, vbo, NULL); + } + return SHC.drw_bone_point; +} + +Batch *DRW_cache_bone_point_wire_outline_get(void) +{ + if (!SHC.drw_bone_point_wire) { + VertexBuffer *vbo = sphere_wire_vbo(0.05f); + SHC.drw_bone_point_wire = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_bone_point_wire; +} + +Batch *DRW_cache_bone_arrows_get(void) +{ + if (!SHC.drw_bone_arrows) { + VertexBuffer *vbo = fill_arrows_vbo(0.25f); + SHC.drw_bone_arrows = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_bone_arrows; +} /* Object Center */ Batch *DRW_cache_single_vert_get(void) diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index efcdbfcc1a8..809d8be8422 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -53,6 +53,13 @@ struct Batch *DRW_cache_lamp_sunrays_get(void); /* Speaker */ struct Batch *DRW_cache_speaker_get(void); +/* Bones */ +struct Batch *DRW_cache_bone_octahedral_get(void); +struct Batch *DRW_cache_bone_octahedral_wire_outline_get(void); +struct Batch *DRW_cache_bone_point_get(void); +struct Batch *DRW_cache_bone_point_wire_outline_get(void); +struct Batch *DRW_cache_bone_arrows_get(void); + /* Meshes */ struct Batch *DRW_cache_wire_overlay_get(struct Object *ob); struct Batch *DRW_cache_wire_outline_get(struct Object *ob); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index f671cbc85e2..ccd3198de4f 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -54,7 +54,8 @@ #include "UI_resources.h" #include "object_mode.h" -#include "edit_mode.h" +#include "edit_armature_mode.h" +#include "edit_mesh_mode.h" #include "clay.h" #define MAX_ATTRIB_NAME 32 @@ -109,6 +110,7 @@ struct DRWInterface { /* matrices locations */ int modelview; int projection; + int view; int modelviewprojection; int viewprojection; int normal; @@ -327,6 +329,7 @@ static DRWInterface *DRW_interface_create(GPUShader *shader) interface->modelview = GPU_shader_get_uniform(shader, "ModelViewMatrix"); interface->projection = GPU_shader_get_uniform(shader, "ProjectionMatrix"); + interface->view = GPU_shader_get_uniform(shader, "ViewMatrix"); interface->viewprojection = GPU_shader_get_uniform(shader, "ViewProjectionMatrix"); interface->modelviewprojection = GPU_shader_get_uniform(shader, "ModelViewProjectionMatrix"); interface->normal = GPU_shader_get_uniform(shader, "NormalMatrix"); @@ -794,6 +797,9 @@ static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*o if (interface->projection != -1) { GPU_shader_uniform_vector(shgroup->shader, interface->projection, 16, 1, (float *)rv3d->winmat); } + if (interface->view != -1) { + GPU_shader_uniform_vector(shgroup->shader, interface->view, 16, 1, (float *)rv3d->viewmat); + } if (interface->modelview != -1) { GPU_shader_uniform_vector(shgroup->shader, interface->modelview, 16, 1, (float *)mv); } @@ -1031,7 +1037,10 @@ void DRW_draw_mode_overlays(void) switch (mode) { case CTX_MODE_EDIT_MESH: - EDIT_draw(); + EDIT_MESH_draw(); + break; + case CTX_MODE_EDIT_ARMATURE: + EDIT_ARMATURE_draw(); break; case CTX_MODE_OBJECT: OBJECT_draw(); @@ -1056,7 +1065,10 @@ void DRW_mode_cache_init(void) switch (mode) { case CTX_MODE_EDIT_MESH: - EDIT_cache_init(); + EDIT_MESH_cache_init(); + break; + case CTX_MODE_EDIT_ARMATURE: + EDIT_ARMATURE_cache_init(); break; case CTX_MODE_OBJECT: OBJECT_cache_init(); @@ -1071,7 +1083,10 @@ void DRW_mode_cache_populate(Object *ob) switch (mode) { case CTX_MODE_EDIT_MESH: - EDIT_cache_populate(ob); + EDIT_MESH_cache_populate(ob); + break; + case CTX_MODE_EDIT_ARMATURE: + EDIT_ARMATURE_cache_populate(ob); break; case CTX_MODE_OBJECT: OBJECT_cache_populate(ob); @@ -1086,7 +1101,10 @@ void DRW_mode_cache_finish(void) switch (mode) { case CTX_MODE_EDIT_MESH: - EDIT_cache_finish(); + EDIT_MESH_cache_finish(); + break; + case CTX_MODE_EDIT_ARMATURE: + EDIT_ARMATURE_cache_finish(); break; case CTX_MODE_OBJECT: OBJECT_cache_finish(); diff --git a/source/blender/draw/intern/draw_mode_pass.c b/source/blender/draw/intern/draw_mode_pass.c index 6c041294d34..9e71de01070 100644 --- a/source/blender/draw/intern/draw_mode_pass.c +++ b/source/blender/draw/intern/draw_mode_pass.c @@ -82,6 +82,8 @@ static DRWPass *wire_overlay_hidden_wire; static DRWPass *wire_outline; static DRWPass *non_meshes; static DRWPass *ob_center; +static DRWPass *bone_solid; +static DRWPass *bone_wire; static DRWShadingGroup *shgroup_dynlines_uniform_color(DRWPass *pass, float color[4]) { @@ -141,6 +143,32 @@ static DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Batch return grp; } +static DRWShadingGroup *shgroup_instance_objspace_solid(DRWPass *pass, struct Batch *geom, float (*obmat)[4]) +{ + static float light[3] = {0.0f, 0.0f, 1.0f}; + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); + DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + DRW_shgroup_attrib_float(grp, "color", 4); + DRW_shgroup_uniform_mat4(grp, "ModelMatrix", (float *)obmat); + DRW_shgroup_uniform_vec3(grp, "light", light, 1); + + return grp; +} + +static DRWShadingGroup *shgroup_instance_objspace_wire(DRWPass *pass, struct Batch *geom, float (*obmat)[4]) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); + DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + DRW_shgroup_attrib_float(grp, "color", 4); + DRW_shgroup_uniform_mat4(grp, "ModelMatrix", (float *)obmat); + + return grp; +} + static DRWShadingGroup *shgroup_instance_axis_names(DRWPass *pass, struct Batch *geom) { GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS); @@ -173,7 +201,9 @@ void DRW_mode_passes_setup(DRWPass **psl_wire_overlay, DRWPass **psl_wire_overlay_hidden_wire, DRWPass **psl_wire_outline, DRWPass **psl_non_meshes, - DRWPass **psl_ob_center) + DRWPass **psl_ob_center, + DRWPass **psl_bone_solid, + DRWPass **psl_bone_wire) { UI_GetThemeColor4fv(TH_WIRE, colorWire); UI_GetThemeColor4fv(TH_WIRE_EDIT, colorWireEdit); @@ -198,7 +228,7 @@ void DRW_mode_passes_setup(DRWPass **psl_wire_overlay, if (psl_wire_overlay_hidden_wire) { /* This pass can draw mesh edges top of Shaded Meshes without any Z fighting */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND; + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND; *psl_wire_overlay_hidden_wire = DRW_pass_create("Wire Overlays Pass", state); } @@ -210,6 +240,18 @@ void DRW_mode_passes_setup(DRWPass **psl_wire_overlay, *psl_wire_outline = DRW_pass_create("Wire + Outlines Pass", state); } + if (psl_bone_solid) { + /* Solid bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS; + *psl_bone_solid = DRW_pass_create("Bone Solid Pass", state); + } + + if (psl_bone_wire) { + /* Wire bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND; + *psl_bone_wire = DRW_pass_create("Bone Wire Pass", state); + } + if (psl_non_meshes) { /* Non Meshes Pass (Camera, empties, lamps ...) */ struct Batch *geom; @@ -318,6 +360,8 @@ void DRW_mode_passes_setup(DRWPass **psl_wire_overlay, wire_outline = (psl_wire_outline) ? *psl_wire_outline : NULL; non_meshes = (psl_non_meshes) ? *psl_non_meshes : NULL; ob_center = (psl_ob_center) ? *psl_ob_center : NULL; + bone_solid = (psl_bone_solid) ? *psl_bone_solid : NULL; + bone_wire = (psl_bone_wire) ? *psl_bone_wire : NULL; } /* ******************************************** WIRES *********************************************** */ @@ -564,3 +608,106 @@ void DRW_shgroup_object_center(Object *ob) DRW_shgroup_dynamic_call_add(center_deselected, ob->obmat[3]); } } + +/* *************************** ARMATURES ***************************** */ + +static Object *current_armature; +/* Reset when changing current_armature */ +static DRWShadingGroup *bone_octahedral_solid; +static DRWShadingGroup *bone_octahedral_wire; +static DRWShadingGroup *bone_point_solid; +static DRWShadingGroup *bone_point_wire; +static DRWShadingGroup *bone_axes; + +/* this function set the object space to use + * for all subsequent DRW_shgroup_bone_*** calls */ +static void DRW_shgroup_armature(Object *ob) +{ + current_armature = ob; + bone_octahedral_solid = NULL; + bone_octahedral_wire = NULL; + bone_point_solid = NULL; + bone_point_wire = NULL; + bone_axes = NULL; +} + +void DRW_shgroup_armature_object(Object *ob) +{ + float *color; + draw_object_wire_theme(ob, &color); + + DRW_shgroup_armature(ob); + draw_armature_pose(ob, color); +} + +void DRW_shgroup_armature_pose(Object *ob) +{ + DRW_shgroup_armature(ob); + draw_armature_pose(ob, NULL); +} + +void DRW_shgroup_armature_edit(Object *ob) +{ + DRW_shgroup_armature(ob); + draw_armature_edit(ob); +} + +/* Octahedral */ +void DRW_shgroup_bone_octahedral_solid(const float (*bone_mat)[4], const float color[4]) +{ + if (bone_octahedral_solid == NULL) { + struct Batch *geom = DRW_cache_bone_octahedral_get(); + bone_octahedral_solid = shgroup_instance_objspace_solid(bone_solid, geom, current_armature->obmat); + } + + DRW_shgroup_dynamic_call_add(bone_octahedral_solid, bone_mat, color); +} + +void DRW_shgroup_bone_octahedral_wire(const float (*bone_mat)[4], const float color[4]) +{ + if (bone_octahedral_wire == NULL) { + struct Batch *geom = DRW_cache_bone_octahedral_wire_outline_get(); + bone_octahedral_wire = shgroup_instance_objspace_wire(bone_wire, geom, current_armature->obmat); + } + + DRW_shgroup_dynamic_call_add(bone_octahedral_wire, bone_mat, color); +} + +/* Head and tail sphere */ +void DRW_shgroup_bone_point_solid(const float (*bone_mat)[4], const float color[4]) +{ + if (bone_point_solid == NULL) { + struct Batch *geom = DRW_cache_bone_point_get(); + bone_point_solid = shgroup_instance_objspace_solid(bone_solid, geom, current_armature->obmat); + } + + DRW_shgroup_dynamic_call_add(bone_point_solid, bone_mat, color); +} + +void DRW_shgroup_bone_point_wire(const float (*bone_mat)[4], const float color[4]) +{ + if (bone_point_wire == NULL) { + struct Batch *geom = DRW_cache_bone_point_wire_outline_get(); + bone_point_wire = shgroup_instance_objspace_wire(bone_wire, geom, current_armature->obmat); + } + + DRW_shgroup_dynamic_call_add(bone_point_wire, bone_mat, color); +} + +/* Axes */ +void DRW_shgroup_bone_axes(const float (*bone_mat)[4], const float color[4]) +{ + if (bone_axes == NULL) { + struct Batch *geom = DRW_cache_bone_arrows_get(); + bone_axes = shgroup_instance_objspace_wire(bone_wire, geom, current_armature->obmat); + } + + DRW_shgroup_dynamic_call_add(bone_axes, bone_mat, color); +} + + +void DRW_shgroup_bone_relationship_lines(const float head[3], const float tail[3]) +{ + DRW_shgroup_dynamic_call_add(relationship_lines, head); + DRW_shgroup_dynamic_call_add(relationship_lines, tail); +} diff --git a/source/blender/draw/intern/draw_mode_pass.h b/source/blender/draw/intern/draw_mode_pass.h index c0d66cef347..53322729f0c 100644 --- a/source/blender/draw/intern/draw_mode_pass.h +++ b/source/blender/draw/intern/draw_mode_pass.h @@ -34,7 +34,9 @@ void DRW_mode_passes_setup(struct DRWPass **psl_wire_overlay, struct DRWPass **psl_wire_overlay_hidden_wire, struct DRWPass **psl_wire_outline, struct DRWPass **psl_non_meshes, - struct DRWPass **psl_ob_center); + struct DRWPass **psl_ob_center, + struct DRWPass **psl_bone_solid, + struct DRWPass **psl_bone_wire); void DRW_shgroup_wire_overlay(struct Object *ob); void DRW_shgroup_wire_outline(struct Object *ob, const bool do_front, const bool do_back, const bool do_outline); @@ -44,4 +46,19 @@ void DRW_shgroup_speaker(struct Object *ob); void DRW_shgroup_relationship_lines(struct Object *ob); void DRW_shgroup_object_center(struct Object *ob); +void DRW_shgroup_armature_object(struct Object *ob); +void DRW_shgroup_armature_edit(struct Object *ob); +void DRW_shgroup_armature_pose(struct Object *ob); + +void DRW_shgroup_bone_octahedral_solid(const float (*arm_mat)[4], const float color[4]); +void DRW_shgroup_bone_octahedral_wire(const float (*arm_mat)[4], const float color[4]); +void DRW_shgroup_bone_point_solid(const float (*arm_mat)[4], const float color[4]); +void DRW_shgroup_bone_point_wire(const float (*arm_mat)[4], const float color[4]); +void DRW_shgroup_bone_relationship_lines(const float head[3], const float tail[3]); +void DRW_shgroup_bone_axes(const float (*arm_mat)[4], const float color[4]); + +/* draw_armature.c */ +void draw_armature_edit(struct Object *ob); +void draw_armature_pose(struct Object *ob, const float const_color[4]); + #endif /* __DRAW_MODE_PASS_H__ */
\ No newline at end of file |