diff options
author | Antony Riakiotakis <kalast@gmail.com> | 2015-06-10 19:38:23 +0300 |
---|---|---|
committer | Antony Riakiotakis <kalast@gmail.com> | 2015-06-10 19:38:23 +0300 |
commit | 080cf9332bc9d71e0e14326bc8efdf06b738dea1 (patch) | |
tree | e8531a509dca4d8253aa19d89edc68152421f9e5 /source/blender/editors/space_view3d | |
parent | 6d495cc4ef071171ff0686b2be898a41e05b8051 (diff) | |
parent | 9676642cc94599b3419c9aaa5cf1aae2fbbd235f (diff) |
Merge branch 'gooseberry' into temp_motionpathstemp_motionpaths
Conflicts:
source/blender/blenkernel/intern/object.c
Diffstat (limited to 'source/blender/editors/space_view3d')
22 files changed, 2064 insertions, 714 deletions
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index ab69e67361d..57c497a2a4d 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -30,6 +30,7 @@ set(INC ../../makesrna ../../render/extern/include ../../windowmanager + ../../depsgraph ../../../../intern/guardedalloc ../../../../intern/glew-mx ../../../../intern/smoke/extern @@ -45,6 +46,7 @@ set(SRC drawmesh.c drawobject.c drawsimdebug.c + drawstrands.c drawvolume.c space_view3d.c view3d_buttons.c diff --git a/source/blender/editors/space_view3d/SConscript b/source/blender/editors/space_view3d/SConscript index a21da940906..78f24948070 100644 --- a/source/blender/editors/space_view3d/SConscript +++ b/source/blender/editors/space_view3d/SConscript @@ -48,6 +48,7 @@ incs = [ '../../makesrna', '../../render/extern/include', '../../windowmanager', + '../../depsgraph', ] if env['WITH_BF_PYTHON']: diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c index d8b18140cde..d753ad68fcc 100644 --- a/source/blender/editors/space_view3d/drawanimviz.c +++ b/source/blender/editors/space_view3d/drawanimviz.c @@ -51,7 +51,6 @@ #include "BIF_gl.h" -#include "ED_armature.h" #include "ED_keyframes_draw.h" diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index 755c633531d..b374ce64319 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -588,15 +588,19 @@ static DMDrawOption draw_tface__set_draw(MTFace *tface, const bool UNUSED(has_mc return DM_DRAW_OPTION_NORMAL; } -static void update_tface_color_layer(DerivedMesh *dm) +static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol) { MTFace *tface = DM_get_tessface_data_layer(dm, CD_MTFACE); MFace *mface = dm->getTessFaceArray(dm); MCol *finalCol; int i, j; - MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL); - if (!mcol) - mcol = dm->getTessFaceDataArray(dm, CD_MCOL); + MCol *mcol = NULL; + + if (use_mcol) { + mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL); + if (!mcol) + mcol = dm->getTessFaceDataArray(dm, CD_MCOL); + } if (CustomData_has_layer(&dm->faceData, CD_TEXTURE_MCOL)) { finalCol = CustomData_get_layer(&dm->faceData, CD_TEXTURE_MCOL); @@ -771,7 +775,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl) for (a = 0, mp = mface; a < totpoly; a++, mtpoly++, mp++) { short matnr = mp->mat_nr; - int mf_smooth = mp->flag & ME_SMOOTH; + const bool mf_smooth = (mp->flag & ME_SMOOTH) != 0; Material *mat = (me->mat) ? me->mat[matnr] : NULL; int mode = mat ? mat->game.flag : GEMAT_INVISIBLE; @@ -937,7 +941,7 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d else { drawTFace_userData userData; - update_tface_color_layer(dm); + update_tface_color_layer(dm, !(ob->mode & OB_MODE_TEXTURE_PAINT)); userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE); userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE); @@ -1103,7 +1107,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Mesh *me = ob->data; TexMatCallback data = {scene, ob, me, dm}; bool (*set_face_cb)(void *, int); - int glsl, picking = (G.f & G_PICKSEL); + bool glsl, picking = (G.f & G_PICKSEL) != 0; /* face hiding callback depending on mode */ if (ob == scene->obedit) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index b44da8a70a6..05a2d5b3ddc 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -54,11 +54,13 @@ #include "BKE_anim.h" /* for the where_on_path function */ #include "BKE_armature.h" #include "BKE_camera.h" +#include "BKE_colortools.h" #include "BKE_constraint.h" /* for the get_constraint_target function */ #include "BKE_curve.h" #include "BKE_DerivedMesh.h" #include "BKE_deform.h" #include "BKE_displist.h" +#include "BKE_editstrands.h" #include "BKE_font.h" #include "BKE_global.h" #include "BKE_image.h" @@ -216,6 +218,7 @@ static void drawcube_size(float size); static void drawcircle_size(float size); static void draw_empty_sphere(float size); static void draw_empty_cone(float size); +static void draw_box(float vec[8][3], bool solid); static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac) { @@ -302,11 +305,12 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt) if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) return true; - if (BKE_scene_use_new_shading_nodes(scene)) + if (v3d->drawtype == OB_TEXTURE) + return (scene->gm.matmode == GAME_MAT_GLSL && !BKE_scene_use_new_shading_nodes(scene)); + else if (v3d->drawtype == OB_MATERIAL && dt > OB_SOLID) + return true; + else return false; - - return ((scene->gm.matmode == GAME_MAT_GLSL && v3d->drawtype == OB_TEXTURE) || - (v3d->drawtype == OB_MATERIAL)) && (dt > OB_SOLID); } static bool check_alpha_pass(Base *base) @@ -402,13 +406,13 @@ static const float cosval[CIRCLE_RESOL] = { static void draw_xyz_wire(const float c[3], float size, int axis) { - float v1[3] = {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f}; + float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3] = {0.0f, 0.0f, 0.0f}; float dim = size * 0.1f; float dx[3], dy[3], dz[3]; - dx[0] = dim; dx[1] = 0.f; dx[2] = 0.f; - dy[0] = 0.f; dy[1] = dim; dy[2] = 0.f; - dz[0] = 0.f; dz[1] = 0.f; dz[2] = dim; + dx[0] = dim; dx[1] = 0.0f; dx[2] = 0.0f; + dy[0] = 0.0f; dy[1] = dim; dy[2] = 0.0f; + dz[0] = 0.0f; dz[1] = 0.0f; dz[2] = dim; switch (axis) { case 0: /* x axis */ @@ -424,7 +428,7 @@ static void draw_xyz_wire(const float c[3], float size, int axis) glVertex3fv(v2); /* top left to bottom right */ - mul_v3_fl(dy, 2.f); + mul_v3_fl(dy, 2.0f); add_v3_v3(v1, dy); sub_v3_v3(v2, dy); @@ -447,7 +451,7 @@ static void draw_xyz_wire(const float c[3], float size, int axis) glVertex3fv(v2); /* top left to center */ - mul_v3_fl(dy, 2.f); + mul_v3_fl(dy, 2.0f); add_v3_v3(v1, dy); copy_v3_v3(v2, c); @@ -465,12 +469,12 @@ static void draw_xyz_wire(const float c[3], float size, int axis) glVertex3fv(v1); - mul_v3_fl(dx, 2.f); + mul_v3_fl(dx, 2.0f); add_v3_v3(v1, dx); glVertex3fv(v1); - mul_v3_fl(dz, 2.f); + mul_v3_fl(dz, 2.0f); sub_v3_v3(v1, dx); sub_v3_v3(v1, dz); @@ -483,7 +487,6 @@ static void draw_xyz_wire(const float c[3], float size, int axis) glEnd(); break; } - } void drawaxes(float size, char drawtype) @@ -597,10 +600,10 @@ void drawaxes(float size, char drawtype) } -/* Function to draw an Image on a empty Object */ +/* Function to draw an Image on an empty Object */ static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4]) { - Image *ima = (Image *)ob->data; + Image *ima = ob->data; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, ob->iuser, NULL); float scale, ofs_x, ofs_y, sca_x, sca_y; @@ -640,16 +643,13 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char sca_y = 1.0f; } - /* Calculate the scale center based on objects origin */ + /* Calculate the scale center based on object's origin */ ofs_x = ob->ima_ofs[0] * ima_x; ofs_y = ob->ima_ofs[1] * ima_y; glMatrixMode(GL_MODELVIEW); glPushMatrix(); - /* Make sure we are drawing at the origin */ - glTranslatef(0.0f, 0.0f, 0.0f); - /* Calculate Image scale */ scale = (ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y)); @@ -943,7 +943,7 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo /* ******************** primitive drawing ******************* */ -/* draws a cube on given the scaling of the cube, assuming that +/* draws a cube given the scaling of the cube, assuming that * all required matrices have been set (used for drawing empties) */ static void drawcube_size(float size) @@ -1025,8 +1025,6 @@ static void drawshadbuflimits(Lamp *la, float mat[4][4]) glPointSize(1.0); } - - static void spotvolume(float lvec[3], float vvec[3], const float inp) { /* camera is at 0,0,0 */ @@ -1035,8 +1033,8 @@ static void spotvolume(float lvec[3], float vvec[3], const float inp) normalize_v3(lvec); normalize_v3(vvec); /* is this the correct vector ? */ - cross_v3_v3v3(temp, vvec, lvec); /* equation for a plane through vvec en lvec */ - cross_v3_v3v3(plane, lvec, temp); /* a plane perpendicular to this, parrallel with lvec */ + cross_v3_v3v3(temp, vvec, lvec); /* equation for a plane through vvec and lvec */ + cross_v3_v3v3(plane, lvec, temp); /* a plane perpendicular to this, parallel with lvec */ /* vectors are exactly aligned, use the X axis, this is arbitrary */ if (normalize_v3(plane) == 0.0f) @@ -1149,6 +1147,52 @@ static void draw_transp_spot_volume(Lamp *la, float x, float z) glCullFace(GL_BACK); } +#ifdef WITH_GAMEENGINE +static void draw_transp_sun_volume(Lamp *la) +{ + float box[8][3]; + + /* construct box */ + box[0][0] = box[1][0] = box[2][0] = box[3][0] = -la->shadow_frustum_size; + box[4][0] = box[5][0] = box[6][0] = box[7][0] = +la->shadow_frustum_size; + box[0][1] = box[1][1] = box[4][1] = box[5][1] = -la->shadow_frustum_size; + box[2][1] = box[3][1] = box[6][1] = box[7][1] = +la->shadow_frustum_size; + box[0][2] = box[3][2] = box[4][2] = box[7][2] = -la->clipend; + box[1][2] = box[2][2] = box[5][2] = box[6][2] = -la->clipsta; + + /* draw edges */ + draw_box(box, false); + + /* draw faces */ + glEnable(GL_CULL_FACE); + glEnable(GL_BLEND); + glDepthMask(0); + + /* draw backside darkening */ + glCullFace(GL_FRONT); + + glBlendFunc(GL_ZERO, GL_SRC_ALPHA); + glColor4f(0.0f, 0.0f, 0.0f, 0.4f); + + draw_box(box, true); + + /* draw front side lighting */ + glCullFace(GL_BACK); + + glBlendFunc(GL_ONE, GL_ONE); + glColor4f(0.2f, 0.2f, 0.2f, 1.0f); + + draw_box(box, true); + + /* restore state */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_BLEND); + glDepthMask(1); + glDisable(GL_CULL_FACE); + glCullFace(GL_BACK); +} +#endif + static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact) { @@ -1161,7 +1205,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, unsigned char curcol[4]; unsigned char col[4]; - /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */ + /* cone can't be drawn for duplicated lamps, because duplilist would be freed */ /* the moment of view3d_draw_transp() call */ const bool is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object); const bool drawcone = ((dt > OB_WIRE) && @@ -1171,7 +1215,22 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, !(base->flag & OB_FROMDUPLI) && !is_view); - if (drawcone && !v3d->transp) { +#ifdef WITH_GAMEENGINE + const bool drawshadowbox = ( + (rv3d->rflag & RV3D_IS_GAME_ENGINE) && + (dt > OB_WIRE) && + !(G.f & G_PICKSEL) && + (la->type == LA_SUN) && + ((la->mode & LA_SHAD_BUF) || + (la->mode & LA_SHAD_RAY)) && + (la->mode & LA_SHOW_SHADOW_BOX) && + !(base->flag & OB_FROMDUPLI) && + !is_view); +#else + const bool drawshadowbox = false; +#endif + + if ((drawcone || drawshadowbox) && !v3d->transp) { /* in this case we need to draw delayed */ ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag); return; @@ -1310,7 +1369,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, x *= y; /* draw the circle/square at the end of the cone */ - glTranslatef(0.0, 0.0, x); + glTranslatef(0.0, 0.0, x); if (la->mode & LA_SQUARE) { float tvec[3]; float z_abs = fabsf(z); @@ -1416,6 +1475,13 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, dir = -dir; } } + +#ifdef WITH_GAMEENGINE + if (drawshadowbox) { + draw_transp_sun_volume(la); + } +#endif + } else if (la->type == LA_AREA) { setlinestyle(3); @@ -1499,10 +1565,10 @@ static void draw_limit_line(float sta, float end, const short dflag, unsigned in static void draw_focus_cross(float dist, float size) { glBegin(GL_LINES); - glVertex3f(-size, 0.f, -dist); - glVertex3f(size, 0.f, -dist); - glVertex3f(0.f, -size, -dist); - glVertex3f(0.f, size, -dist); + glVertex3f(-size, 0.0f, -dist); + glVertex3f(size, 0.0f, -dist); + glVertex3f(0.0f, -size, -dist); + glVertex3f(0.0f, size, -dist); glEnd(); } @@ -1555,8 +1621,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D BKE_tracking_get_camera_object_matrix(scene, base->object, mat); /* we're compensating camera size for bundles size, - * to make it so bundles are always displayed with the same size - */ + * to make it so bundles are always displayed with the same size */ copy_v3_v3(camera_size, base->object->size); if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) mul_v3_fl(camera_size, tracking_object->scale); @@ -1624,7 +1689,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D glColor3ubv(ob_wire_col); } - glLineWidth(2.f); + glLineWidth(2.0f); glDisable(GL_LIGHTING); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); @@ -1632,7 +1697,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_LIGHTING); - glLineWidth(1.f); + glLineWidth(1.0f); } if ((dflag & DRAW_CONSTCOLOR) == 0) { @@ -1746,6 +1811,238 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, GPU_select_load_id(base->selcol); } +static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], const GLenum mode) +{ + glBegin(mode); + glVertex3fv(near_plane[0]); + glVertex3fv(far_plane[0]); + glVertex3fv(far_plane[1]); + glVertex3fv(near_plane[1]); + glEnd(); + + glBegin(mode); + glVertex3fv(near_plane[1]); + glVertex3fv(far_plane[1]); + glVertex3fv(far_plane[2]); + glVertex3fv(near_plane[2]); + glEnd(); + + glBegin(mode); + glVertex3fv(near_plane[2]); + glVertex3fv(near_plane[1]); + glVertex3fv(far_plane[1]); + glVertex3fv(far_plane[2]); + glEnd(); + + glBegin(mode); + glVertex3fv(far_plane[0]); + glVertex3fv(near_plane[0]); + glVertex3fv(near_plane[3]); + glVertex3fv(far_plane[3]); + glEnd(); +} + +/* camera frame */ +static void drawcamera_frame(float vec[4][3], const GLenum mode) +{ + glBegin(mode); + glVertex3fv(vec[0]); + glVertex3fv(vec[1]); + glVertex3fv(vec[2]); + glVertex3fv(vec[3]); + glEnd(); +} + +/* center point to camera frame */ +static void drawcamera_framelines(float vec[4][3], float origin[3]) +{ + glBegin(GL_LINE_STRIP); + glVertex3fv(vec[1]); + glVertex3fv(origin); + glVertex3fv(vec[0]); + glVertex3fv(vec[3]); + glVertex3fv(origin); + glVertex3fv(vec[2]); + glEnd(); +} + +static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob) +{ + return (ob == v3d->camera) && + (scene->r.scemode & R_MULTIVIEW) != 0 && + (v3d->stereo3d_flag); +} + +static void drawcamera_stereo3d( + Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const Camera *cam, + float vec[4][3], float drawsize, const float scale[3]) +{ + int i, j; + float obmat[4][4]; + float vec_lr[2][4][3]; + const float fac = (cam->stereo.pivot == CAM_S3D_PIVOT_CENTER) ? 2.0f : 1.0f; + float origin[2][3] = {{0}}; + float tvec[3]; + const Camera *cam_lr[2]; + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + + const bool is_stereo3d_cameras = (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS) && (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D); + const bool is_stereo3d_plane = (v3d->stereo3d_flag & V3D_S3D_DISPPLANE) && (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D); + const bool is_stereo3d_volume = (v3d->stereo3d_flag & V3D_S3D_DISPVOLUME); + + zero_v3(tvec); + + glPushMatrix(); + + for (i = 0; i < 2; i++) { + ob = BKE_camera_multiview_render(scene, ob, names[i]); + cam_lr[i] = ob->data; + + glLoadMatrixf(rv3d->viewmat); + BKE_camera_multiview_model_matrix(&scene->r, ob, names[i], obmat); + glMultMatrixf(obmat); + + copy_m3_m3(vec_lr[i], vec); + copy_v3_v3(vec_lr[i][3], vec[3]); + + if (cam->stereo.convergence_mode == CAM_S3D_OFFAXIS) { + const float shift_x = + ((BKE_camera_multiview_shift_x(&scene->r, ob, names[i]) - cam->shiftx) * + (drawsize * scale[0] * fac)); + + for (j = 0; j < 4; j++) { + vec_lr[i][j][0] += shift_x; + } + } + + if (is_stereo3d_cameras) { + /* camera frame */ + drawcamera_frame(vec_lr[i], GL_LINE_LOOP); + + /* center point to camera frame */ + drawcamera_framelines(vec_lr[i], tvec); + } + + /* connecting line */ + mul_m4_v3(obmat, origin[i]); + + /* convergence plane */ + if (is_stereo3d_plane || is_stereo3d_volume) { + for (j = 0; j < 4; j++) { + mul_m4_v3(obmat, vec_lr[i][j]); + } + } + } + + + /* the remaining drawing takes place in the view space */ + glLoadMatrixf(rv3d->viewmat); + + if (is_stereo3d_cameras) { + /* draw connecting lines */ + glPushAttrib(GL_ENABLE_BIT); + + glLineStipple(2, 0xAAAA); + glEnable(GL_LINE_STIPPLE); + + glBegin(GL_LINES); + glVertex3fv(origin[0]); + glVertex3fv(origin[1]); + glEnd(); + glPopAttrib(); + } + + /* draw convergence plane*/ + if (is_stereo3d_plane) { + float axis_center[3], screen_center[3]; + float world_plane[4][3]; + float local_plane[4][3]; + float offset; + + mid_v3_v3v3(axis_center, origin[0], origin[1]); + + for (i = 0; i < 4; i++) { + mid_v3_v3v3(world_plane[i], vec_lr[0][i], vec_lr[1][i]); + sub_v3_v3v3(local_plane[i], world_plane[i], axis_center); + } + + mid_v3_v3v3(screen_center, world_plane[0], world_plane[2]); + offset = cam->stereo.convergence_distance / len_v3v3(screen_center, axis_center); + + for (i = 0; i < 4; i++) { + mul_v3_fl(local_plane[i], offset); + add_v3_v3(local_plane[i], axis_center); + } + + glColor3f(0.0f, 0.0f, 0.0f); + + /* camera frame */ + drawcamera_frame(local_plane, GL_LINE_LOOP); + + if (v3d->stereo3d_convergence_alpha > 0.0f) { + glEnable(GL_BLEND); + glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + + glColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha); + + drawcamera_frame(local_plane, GL_QUADS); + + glDisable(GL_BLEND); + glDepthMask(1); /* restore write in zbuffer */ + } + } + + /* draw convergence plane*/ + if (is_stereo3d_volume) { + float screen_center[3]; + float near_plane[4][3], far_plane[4][3]; + float offset; + int j; + + for (i = 0; i < 2; i++) { + mid_v3_v3v3(screen_center, vec_lr[i][0], vec_lr[i][2]); + + offset = len_v3v3(screen_center, origin[i]); + + for (j = 0; j < 4; j++) { + sub_v3_v3v3(near_plane[j], vec_lr[i][j], origin[i]); + mul_v3_fl(near_plane[j], cam_lr[i]->clipsta / offset); + add_v3_v3(near_plane[j], origin[i]); + + sub_v3_v3v3(far_plane[j], vec_lr[i][j], origin[i]); + mul_v3_fl(far_plane[j], cam_lr[i]->clipend / offset); + add_v3_v3(far_plane[j], origin[i]); + } + + /* camera frame */ + glColor3f(0.0f, 0.0f, 0.0f); + + drawcamera_frame(near_plane, GL_LINE_LOOP); + drawcamera_frame(far_plane, GL_LINE_LOOP); + drawcamera_volume(near_plane, far_plane, GL_LINE_LOOP); + + if (v3d->stereo3d_volume_alpha > 0.0f) { + glEnable(GL_BLEND); + glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + + if (i == 0) + glColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha); + else + glColor4f(1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha); + + drawcamera_frame(near_plane, GL_QUADS); + drawcamera_frame(far_plane, GL_QUADS); + drawcamera_volume(near_plane, far_plane, GL_QUADS); + + glDisable(GL_BLEND); + glDepthMask(1); /* restore write in zbuffer */ + } + } + } + + glPopMatrix(); +} + /* flag similar to draw_object() */ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const short dflag, const unsigned char ob_wire_col[4]) @@ -1760,6 +2057,12 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base const bool is_view = (rv3d->persp == RV3D_CAMOB && ob == v3d->camera); MovieClip *clip = BKE_object_movieclip_get(scene, base->object, false); + const bool is_stereo3d = drawcamera_is_stereo3d(scene, v3d, ob); + const bool is_stereo3d_cameras = (ob == scene->camera) && + (scene->r.scemode & R_MULTIVIEW) && + (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) && + (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS); + /* draw data for movie clip set as active for scene */ if (clip) { draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, false); @@ -1796,12 +2099,8 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base glDisable(GL_CULL_FACE); /* camera frame */ - glBegin(GL_LINE_LOOP); - glVertex3fv(vec[0]); - glVertex3fv(vec[1]); - glVertex3fv(vec[2]); - glVertex3fv(vec[3]); - glEnd(); + if (!is_stereo3d_cameras) + drawcamera_frame(vec, GL_LINE_LOOP); if (is_view) return; @@ -1809,20 +2108,12 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base zero_v3(tvec); /* center point to camera frame */ - glBegin(GL_LINE_STRIP); - glVertex3fv(vec[1]); - glVertex3fv(tvec); - glVertex3fv(vec[0]); - glVertex3fv(vec[3]); - glVertex3fv(tvec); - glVertex3fv(vec[2]); - glEnd(); - + if (!is_stereo3d_cameras) + drawcamera_framelines(vec, tvec); /* arrow on top */ tvec[2] = vec[1][2]; /* copy the depth */ - /* draw an outline arrow for inactive cameras and filled * for active cameras. We actually draw both outline+filled * for active cameras so the wire can be seen side-on */ @@ -1872,14 +2163,17 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base glPopMatrix(); } } + + /* stereo cameras drawing */ + if (is_stereo3d) { + drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale); + } } /* flag similar to draw_object() */ static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d), Object *UNUSED(ob), int UNUSED(flag)) { - //Speaker *spk = ob->data; - float vec[3]; int i, j; @@ -1990,9 +2284,9 @@ static void ensure_curve_cache(Scene *scene, Object *object) * here, we also need to check whether display list is * empty or not. * - * The trick below tries to optimie calls to displist + * The trick below tries to optimize calls to displist * creation for cases curve is empty. Meaning, if the curve - * is empty (without splies) bevel list would also be empty. + * is empty (without splines) bevel list would also be empty. * And the thing is, render thread always leaves bevel list * in a proper state. So if bevel list is here and display * list is not we need to make display list. @@ -2270,8 +2564,7 @@ static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3], BMVert *eve = BM_vert_at_index(data->bm, index); if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) { - /* skin nodes: draw a red circle around the root - * node(s) */ + /* skin nodes: draw a red circle around the root node(s) */ if (data->cd_vskin_offset != -1) { const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset); if (vs->flag & MVERT_SKIN_ROOT) { @@ -2337,7 +2630,6 @@ static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVer static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index) { BMEdge *eed; - //unsigned char **cols = userData, *col; drawDMEdgesSel_userData *data = userData; unsigned char *col; @@ -2354,7 +2646,7 @@ static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index) else { col = data->baseCol; } - /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */ + /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */ if (col[3] == 0) return DM_DRAW_OPTION_SKIP; @@ -2751,7 +3043,7 @@ static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *ba data.orig_index_mf_to_mpoly = data.orig_index_mp_to_orig = NULL; } - dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0); + dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, NULL, draw_dm_faces_sel__compareDrawOptions, &data, 0); } static DMDrawOption draw_dm_creases__setDrawOptions(void *userData, int index) @@ -3044,7 +3336,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe } BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { - /* draw selected edges, or edges next to selected verts while draging */ + /* draw selected edges, or edges next to selected verts while dragging */ if (BM_elem_flag_test(eed, BM_ELEM_SELECT) || (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)))) @@ -3082,7 +3374,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe unit->system, B_UNIT_LENGTH, do_split, false); } else { - numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2)); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2)); } view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); @@ -3101,17 +3393,15 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); } - // invert_m4_m4(ob->imat, ob->obmat); // this is already called - BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { BMLoop *l_a, *l_b; if (BM_edge_loop_pair(eed, &l_a, &l_b)) { - /* draw selected edges, or edges next to selected verts while draging */ + /* draw selected edges, or edges next to selected verts while dragging */ if (BM_elem_flag_test(eed, BM_ELEM_SELECT) || (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || BM_elem_flag_test(eed->v2, BM_ELEM_SELECT) || - /* special case, this is useful to show when vertes connected to this edge via a - * face are being transformed */ + /* special case, this is useful to show when verts connected to + * this edge via a face are being transformed */ BM_elem_flag_test(l_a->next->next->v, BM_ELEM_SELECT) || BM_elem_flag_test(l_a->prev->v, BM_ELEM_SELECT) || BM_elem_flag_test(l_b->next->next->v, BM_ELEM_SELECT) || @@ -3161,7 +3451,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe angle = angle_normalized_v3v3(no_a, no_b); - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); } @@ -3186,7 +3476,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe 3, unit->system, B_UNIT_AREA, do_split, false); \ } \ else { \ - numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \ + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, area); \ } \ view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); \ } (void)0 @@ -3304,7 +3594,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe angle = angle_v3v3v3(v1, v2, v3); - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); interp_v3_v3v3(fvec, vmid, v2_local, 0.8f); view3d_cached_text_draw_add(fvec, numstr, numstr_len, 0, txt_flag, col); } @@ -3335,7 +3625,7 @@ static void draw_em_indices(BMEditMesh *em) UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col); BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); view3d_cached_text_draw_add(v->co, numstr, numstr_len, 0, txt_flag, col); } i++; @@ -3347,7 +3637,7 @@ static void draw_em_indices(BMEditMesh *em) UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col); BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); mid_v3_v3v3(pos, e->v1->co, e->v2->co); view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col); } @@ -3361,7 +3651,7 @@ static void draw_em_indices(BMEditMesh *em) BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { BM_face_calc_center_mean(f, pos); - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col); } i++; @@ -3417,7 +3707,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, if (em->bm->selected.last) { BMEditSelection *ese = em->bm->selected.last; - /* face is handeled above */ + /* face is handled above */ #if 0 if (ese->type == BM_FACE) { efa_act = (BMFace *)ese->data; @@ -3532,11 +3822,14 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, } else if (efa_act) { /* even if draw faces is off it would be nice to draw the stipple face - * Make all other faces zero alpha except for the active - * */ - /* col4 is only used by WITH_FREESTYLE, but keeping it here spares some #ifdef's... */ - unsigned char col1[4], col2[4], col3[4], col4[4]; - col1[3] = col2[3] = col4[3] = 0; /* don't draw */ + * Make all other faces zero alpha except for the active */ + unsigned char col1[4], col2[4], col3[4]; +#ifdef WITH_FREESTYLE + unsigned char col4[4]; + col4[3] = 0; /* don't draw */ +#endif + col1[3] = col2[3] = 0; /* don't draw */ + UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3); glEnable(GL_BLEND); @@ -3550,7 +3843,6 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, glDisable(GL_BLEND); glDepthMask(1); /* restore write in zbuffer */ - } /* here starts all fancy draw-extra over */ @@ -3653,7 +3945,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) { if ((v3d->transp == false) && /* not when we draw the transparent pass */ - (ob->mode & OB_MODE_ALL_PAINT) == false) /* not when painting (its distracting) - campbell */ + (ob->mode & OB_MODE_ALL_BRUSH) == false) /* not when painting (its distracting) - campbell */ { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); glDepthMask(0); @@ -3691,7 +3983,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D #endif Mesh *me = ob->data; eWireDrawMode draw_wire = OBDRAW_WIRE_OFF; - int /* totvert,*/ totedge, totface; + bool /* no_verts,*/ no_edges, no_faces; DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); const bool is_obact = (ob == OBACT); int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0; @@ -3714,9 +4006,9 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D draw_wire = OBDRAW_WIRE_ON_DEPTH; /* draw wire after solid using zoffset and depth buffer adjusment */ } - /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/ - totedge = dm->getNumEdges(dm); - totface = dm->getNumTessFaces(dm); + /* check polys instead of tessfaces because of dyntopo where tessfaces don't exist */ + no_edges = (dm->getNumEdges(dm) == 0); + no_faces = (dm->getNumPolys(dm) == 0); /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */ glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); @@ -3725,15 +4017,15 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0) draw_bounding_volume(ob, ob->boundtype); } - else if ((totface == 0 && totedge == 0) || + else if ((no_faces && no_edges) || ((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob))) { glPointSize(1.5); dm->drawVerts(dm); glPointSize(1.0); } - else if (dt == OB_WIRE || totface == 0) { - draw_wire = OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff */ + else if ((dt == OB_WIRE) || no_faces) { + draw_wire = OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff */ } else if (((is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) || check_object_draw_texture(scene, v3d, dt)) @@ -3775,8 +4067,10 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D else dm->drawFacesGLSL(dm, GPU_enable_material); -// if (BKE_bproperty_object_get(ob, "Text")) -// XXX draw_mesh_text(ob, 1); +#if 0 /* XXX */ + if (BKE_bproperty_object_get(ob, "Text")) + draw_mesh_text(ob, 1); +#endif GPU_disable_material(); glFrontFace(GL_CCW); @@ -3894,7 +4188,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } if ((draw_wire != OBDRAW_WIRE_OFF) && /* draw extra wire */ - /* when overriding with render only, don't bother */ + /* when overriding with render only, don't bother */ (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_SOLID) == 0)) { /* When using wireframe object draw in particle edit mode @@ -3924,7 +4218,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */ } - dm->drawEdges(dm, (dt == OB_WIRE || totface == 0), (ob->dtx & OB_DRAW_ALL_EDGES) != 0); + dm->drawEdges(dm, ((dt == OB_WIRE) || no_faces), (ob->dtx & OB_DRAW_ALL_EDGES) != 0); if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) { glDepthMask(1); @@ -3933,7 +4227,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } if (is_obact && BKE_paint_select_vert_test(ob)) { - const int use_depth = (v3d->flag & V3D_ZBUF_SELECT); + const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) != 0; glColor3f(0.0f, 0.0f, 0.0f); glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); @@ -3948,7 +4242,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D dm->release(dm); } -/* returns 1 if nothing was drawn, for detecting to draw an object center */ +/* returns true if nothing was drawn, for detecting to draw an object center */ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const unsigned char ob_wire_col[4], const short dflag) { @@ -3992,7 +4286,9 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 scene->customdata_mask); DM_update_materials(finalDM, ob); - DM_update_materials(cageDM, ob); + if (cageDM != finalDM) { + DM_update_materials(cageDM, ob); + } if (dt > OB_WIRE) { const bool glsl = draw_glsl_material(scene, ob, v3d, dt); @@ -4336,7 +4632,7 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, /** * Only called by #drawDispList - * \return 1 when nothing was drawn + * \return true when nothing was drawn */ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) @@ -4980,7 +5276,7 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix copy_v3_v3(pdd->vd, vec2); pdd->vd += 3; vec[2] = 2.0f * pixsize; - vec[0] = vec[1] = 0.0; + vec[0] = vec[1] = 0.0f; mul_qt_v3(state->rot, vec); if (draw_as == PART_DRAW_AXIS) { copy_v3_v3(vec2, state->co); @@ -5064,7 +5360,7 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d, if (psys->parent) mul_m4_v3(psys->parent->obmat, state->co); - /* create actiual particle data */ + /* create actual particle data */ if (draw_as == PART_DRAW_BB) { bb->offset[0] = part->bb_offset[0]; bb->offset[1] = part->bb_offset[1]; @@ -5089,16 +5385,17 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d, draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd); } -/* unified drawing of all new particle systems draw types except dupli ob & group */ -/* mostly tries to use vertex arrays for speed */ - -/* 1. check that everything is ok & updated */ -/* 2. start initializing things */ -/* 3. initialize according to draw type */ -/* 4. allocate drawing data arrays */ -/* 5. start filling the arrays */ -/* 6. draw the arrays */ -/* 7. clean up */ +/* unified drawing of all new particle systems draw types except dupli ob & group + * mostly tries to use vertex arrays for speed + * + * 1. check that everything is ok & updated + * 2. start initializing things + * 3. initialize according to draw type + * 4. allocate drawing data arrays + * 5. start filling the arrays + * 6. draw the arrays + * 7. clean up + */ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, ParticleSystem *psys, const char ob_dt, const short dflag) @@ -5146,6 +5443,12 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv return; } + /* prepare curvemapping tables */ + if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve) + curvemapping_changed_all(psys->part->clumpcurve); + if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve) + curvemapping_changed_all(psys->part->roughcurve); + /* 2. */ sim.scene = scene; sim.ob = ob; @@ -5291,7 +5594,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv int create_ndata = 0; if (!pdd) - pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticlDrawData"); + pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticleDrawData"); if (part->draw_as == PART_DRAW_REND && part->trail_count > 1) { tot_vec_size *= part->trail_count; @@ -5397,6 +5700,12 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv case PART_DRAW_COL_PARENT: particle_path_color(a, ma_col); break; + case PART_DRAW_COL_TEX: { + ParticleTexture ptex; + psys_get_texture(&sim, pa, &ptex, PAMAP_COLOR, cfra); + copy_v3_v3(ma_col, ptex.color); + break; + } default: weight_to_rgb(ma_col, 1.0f); BLI_assert(0); @@ -5459,8 +5768,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv } if (drawn) { - /* additional things to draw for each particle */ - /* (velocity, size and number) */ + /* additional things to draw for each particle + * (velocity, size and number) */ if ((part->draw & PART_DRAW_VEL) && pdd && pdd->vedata) { copy_v3_v3(pdd->ved, state.co); pdd->ved += 3; @@ -5488,21 +5797,21 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if (part->draw & PART_DRAW_NUM) { if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) { - numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health); + numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health); } else { - numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%d", a); + numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d", a); } } else { if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) { - numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%.2f", pa_health); + numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%.2f", pa_health); } } if (numstr[0]) { - /* in path drawing state.co is the end point */ - /* use worldspace beause object matrix is already applied */ + /* in path drawing state.co is the end point + * use worldspace because object matrix is already applied */ mul_v3_m4v3(vec_txt, ob->imat, state.co); view3d_cached_text_draw_add(vec_txt, numstr, numstr_len, 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol); @@ -5519,7 +5828,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if (draw_as == PART_DRAW_PATH) { ParticleCacheKey **cache, *path; - float /* *cd2=NULL, */ /* UNUSED */ *cdata2 = NULL; + float *cdata2 = NULL; /* setup gl flags */ if (1) { //ob_dt > OB_WIRE) { @@ -5583,11 +5892,13 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv HairKey *hkey = pa->hair; glVertexPointer(3, GL_FLOAT, sizeof(HairKey), hkey->world_co); - - // XXX use proper theme color here -// UI_ThemeColor(TH_NORMAL); + +#if 0 /* XXX use proper theme color here */ + UI_ThemeColor(TH_NORMAL); +#else glColor3f(0.58f, 0.67f, 1.0f); - +#endif + glDrawArrays(GL_LINE_STRIP, 0, pa->totkey); } } @@ -5720,6 +6031,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glColor3fv(col); } break; + case PART_DRAW_COL_TEX: + // TODO + break; default: break; } @@ -5729,7 +6043,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1); } - /* restore & clean up */ if (1) { //ob_dt > OB_WIRE) { if (part->draw_col == PART_DRAW_COL_MAT) @@ -5737,9 +6050,10 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glDisable(GL_COLOR_MATERIAL); } - if (cdata2) + if (cdata2) { MEM_freeN(cdata2); - /* cd2 = */ /* UNUSED */ cdata2 = NULL; + cdata2 = NULL; + } glLineWidth(1.0f); @@ -5748,8 +6062,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { float vec_txt[3]; - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%i", a); - /* use worldspace beause object matrix is already applied */ + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%i", a); + /* use worldspace because object matrix is already applied */ mul_v3_m4v3(vec_txt, ob->imat, cache[a]->co); view3d_cached_text_draw_add(vec_txt, numstr, numstr_len, 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol); @@ -5877,7 +6191,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) PTCacheEditPoint *point; PTCacheEditKey *key; ParticleEditSettings *pset = PE_settings(scene); - int i, k, totpoint = edit->totpoint, timed = pset->flag & PE_FADE_TIME ? pset->fade_frames : 0; + int i, k, totpoint = edit->totpoint, timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : 0; int totkeys = 1; float sel_col[3]; float nosel_col[3]; @@ -6017,7 +6331,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) glColor3fv(nosel_col); /* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/ glBegin(GL_POINTS); - glVertex3fv(key->flag & PEK_USE_WCO ? key->world_co : key->co); + glVertex3fv((key->flag & PEK_USE_WCO) ? key->world_co : key->co); glEnd(); } } @@ -6033,9 +6347,9 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) glShadeModel(GL_FLAT); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); glLineWidth(1.0f); - glPointSize(1.0); + glPointSize(1.0f); } -//static void ob_draw_RE_motion(float com[3],float rotscale[3][3],float tw,float th) + static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, float ith, float drw_size) { float tr[3][3]; @@ -6439,7 +6753,7 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) Nurb *nu; BPoint *bp, *bp1; int a, b, ofs, index; - Curve *cu = (Curve *)ob->data; + Curve *cu = ob->data; index = 0; nu = nurb; @@ -6799,7 +7113,7 @@ static void draw_empty_sphere(float size) static GLuint displist = 0; if (displist == 0) { - GLUquadricObj *qobj; + GLUquadricObj *qobj; displist = glGenLists(1); glNewList(displist, GL_COMPILE); @@ -6830,16 +7144,13 @@ static void draw_empty_sphere(float size) /* draw a cone for use as an empty drawtype */ static void draw_empty_cone(float size) { - float cent = 0; - float radius; + const float radius = size; + GLUquadricObj *qobj = gluNewQuadric(); gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - glPushMatrix(); - radius = size; - glTranslatef(cent, cent, cent); glScalef(radius, size * 2.0f, radius); glRotatef(-90.0, 1.0, 0.0, 0.0); gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1); @@ -6852,7 +7163,7 @@ static void draw_empty_cone(float size) static void drawspiral(const float cent[3], float rad, float tmat[4][4], int start) { float vec[3], vx[3], vy[3]; - const float tot_inv = (1.0f / (float)CIRCLE_RESOL); + const float tot_inv = 1.0f / (float)CIRCLE_RESOL; int a; bool inverse = false; float x, y, fac; @@ -6916,8 +7227,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta } /* draws a circle on x-z plane given the scaling of the circle, assuming that - * all required matrices have been set (used for drawing empties) - */ + * all required matrices have been set (used for drawing empties) */ static void drawcircle_size(float size) { float x, y; @@ -6925,7 +7235,7 @@ static void drawcircle_size(float size) glBegin(GL_LINE_LOOP); - /* coordinates are: cos(degrees * 11.25) = x, sin(degrees*11.25) = y, 0.0f = z */ + /* coordinates are: cos(degrees * 11.25) = x, sin(degrees * 11.25) = y, 0.0f = z */ for (degrees = 0; degrees < CIRCLE_RESOL; degrees++) { x = cosval[degrees]; y = sinval[degrees]; @@ -7069,31 +7379,23 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, PartDeflect *pd = ob->pd; float imat[4][4], tmat[4][4]; float vec[3] = {0.0, 0.0, 0.0}; - float size; - /* scale size of circle etc with the empty drawsize */ - if (ob->type == OB_EMPTY) size = ob->empty_drawsize; - else size = 1.0; + const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f; /* calculus here, is reused in PFIELD_FORCE */ invert_m4_m4(imat, rv3d->viewmatob); -// normalize_v3(imat[0]); /* we don't do this because field doesnt scale either... apart from wind! */ -// normalize_v3(imat[1]); +#if 0 + normalize_v3(imat[0]); /* we don't do this because field doesnt scale either... apart from wind! */ + normalize_v3(imat[1]); +#endif if (pd->forcefield == PFIELD_WIND) { - float force_val; + float force_val = pd->f_strength; if ((dflag & DRAW_CONSTCOLOR) == 0) { ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); } - //if (has_ipo_code(ob->ipo, OB_PD_FSTR)) - // force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra); - //else - { - force_val = pd->f_strength; - } - unit_m4(tmat); force_val *= 0.1f; drawcircball(GL_LINE_LOOP, vec, size, tmat); @@ -7107,14 +7409,7 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, } else if (pd->forcefield == PFIELD_FORCE) { - float ffall_val; - - //if (has_ipo_code(ob->ipo, OB_PD_FFALL)) - // ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, scene->r.cfra); - //else - { - ffall_val = pd->f_power; - } + float ffall_val = pd->f_power; if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); drawcircball(GL_LINE_LOOP, vec, size, imat); @@ -7124,20 +7419,9 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, drawcircball(GL_LINE_LOOP, vec, size * 2.0f, imat); } else if (pd->forcefield == PFIELD_VORTEX) { - float /*ffall_val,*/ force_val; + float force_val = pd->f_strength; unit_m4(tmat); - //if (has_ipo_code(ob->ipo, OB_PD_FFALL)) - // ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, scene->r.cfra); - //else - // ffall_val = pd->f_power; - - //if (has_ipo_code(ob->ipo, OB_PD_FSTR)) - // force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra); - //else - { - force_val = pd->f_strength; - } if ((dflag & DRAW_CONSTCOLOR) == 0) { ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.7f); @@ -7155,25 +7439,19 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, else if (pd->forcefield == PFIELD_GUIDE && ob->type == OB_CURVE) { Curve *cu = ob->data; if ((cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) { - float mindist, guidevec1[4], guidevec2[3]; - - //if (has_ipo_code(ob->ipo, OB_PD_FSTR)) - // mindist = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra); - //else - { - mindist = pd->f_strength; - } + float guidevec1[4], guidevec2[3]; + float mindist = pd->f_strength; if ((dflag & DRAW_CONSTCOLOR) == 0) { ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); } - /*path end*/ + /* path end */ setlinestyle(3); where_on_path(ob, 1.0f, guidevec1, guidevec2, NULL, NULL, NULL); drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat); - /*path beginning*/ + /* path beginning */ setlinestyle(0); where_on_path(ob, 0.0f, guidevec1, guidevec2, NULL, NULL, NULL); drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat); @@ -7244,19 +7522,31 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, setlinestyle(0); } -static void draw_box(float vec[8][3]) +static void draw_box(float vec[8][3], bool solid) { - glBegin(GL_LINE_STRIP); - glVertex3fv(vec[0]); glVertex3fv(vec[1]); glVertex3fv(vec[2]); glVertex3fv(vec[3]); - glVertex3fv(vec[0]); glVertex3fv(vec[4]); glVertex3fv(vec[5]); glVertex3fv(vec[6]); - glVertex3fv(vec[7]); glVertex3fv(vec[4]); - glEnd(); + if (!solid) { + glBegin(GL_LINE_STRIP); + glVertex3fv(vec[0]); glVertex3fv(vec[1]); glVertex3fv(vec[2]); glVertex3fv(vec[3]); + glVertex3fv(vec[0]); glVertex3fv(vec[4]); glVertex3fv(vec[5]); glVertex3fv(vec[6]); + glVertex3fv(vec[7]); glVertex3fv(vec[4]); + glEnd(); - glBegin(GL_LINES); - glVertex3fv(vec[1]); glVertex3fv(vec[5]); - glVertex3fv(vec[2]); glVertex3fv(vec[6]); - glVertex3fv(vec[3]); glVertex3fv(vec[7]); - glEnd(); + glBegin(GL_LINES); + glVertex3fv(vec[1]); glVertex3fv(vec[5]); + glVertex3fv(vec[2]); glVertex3fv(vec[6]); + glVertex3fv(vec[3]); glVertex3fv(vec[7]); + glEnd(); + } + else { + glBegin(GL_QUADS); + glVertex3fv(vec[0]); glVertex3fv(vec[1]); glVertex3fv(vec[2]); glVertex3fv(vec[3]); + glVertex3fv(vec[7]); glVertex3fv(vec[6]); glVertex3fv(vec[5]); glVertex3fv(vec[4]); + glVertex3fv(vec[4]); glVertex3fv(vec[5]); glVertex3fv(vec[1]); glVertex3fv(vec[0]); + glVertex3fv(vec[3]); glVertex3fv(vec[2]); glVertex3fv(vec[6]); glVertex3fv(vec[7]); + glVertex3fv(vec[3]); glVertex3fv(vec[7]); glVertex3fv(vec[4]); glVertex3fv(vec[0]); + glVertex3fv(vec[1]); glVertex3fv(vec[5]); glVertex3fv(vec[6]); glVertex3fv(vec[2]); + glEnd(); + } } static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin) @@ -7350,7 +7640,7 @@ static void draw_bounding_volume(Object *ob, char type) vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2]; vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2]; - draw_box(vec); + draw_box(vec, false); } else { draw_bb_quadric(bb, type, true); @@ -7358,7 +7648,7 @@ static void draw_bounding_volume(Object *ob, char type) } else { if (type == OB_BOUND_BOX) - draw_box(bb->vec); + draw_box(bb->vec, false); else draw_bb_quadric(bb, type, false); } @@ -7394,7 +7684,7 @@ static void drawtexspace(Object *ob) setlinestyle(2); - draw_box(vec); + draw_box(vec, false); setlinestyle(0); } @@ -7581,7 +7871,7 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_ else { if (ob->flag & OB_FROMGROUP) { if (base->flag & (SELECT + BA_WAS_SEL)) { - /* uses darker active color for non-active + selected*/ + /* uses darker active color for non-active + selected */ theme_id = TH_GROUP_ACTIVE; if (scene->basact != base) { @@ -7701,8 +7991,11 @@ static void draw_object_matcap_check(View3D *v3d, Object *ob) v3d->defmaterial->preview = NULL; } /* first time users */ - if (v3d->matcap_icon == 0) + if (v3d->matcap_icon < ICON_MATCAP_01 || + v3d->matcap_icon > ICON_MATCAP_24) + { v3d->matcap_icon = ICON_MATCAP_01; + } if (v3d->defmaterial->preview == NULL) v3d->defmaterial->preview = UI_icon_to_preview(v3d->matcap_icon); @@ -7734,7 +8027,7 @@ static void draw_rigidbody_shape(Object *ob) vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2]; vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2]; - draw_box(vec); + draw_box(vec, false); break; case RB_SHAPE_SPHERE: draw_bb_quadric(bb, OB_BOUND_SPHERE, true); @@ -7773,7 +8066,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short const bool is_picking = (G.f & G_PICKSEL) != 0; const bool has_particles = (ob->particlesystem.first != NULL); const bool is_wire_color = V3D_IS_WIRECOLOR_OBJECT(scene, v3d, ob); - bool particle_skip_object = false; /* Draw particles but not their emitter object. */ + bool skip_object = false; /* Draw particles but not their emitter object. */ + SmokeModifierData *smd = NULL; if (ob != scene->obedit) { if (ob->restrictflag & OB_RESTRICT_VIEW) @@ -7797,17 +8091,37 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (ob->mode == OB_MODE_OBJECT) { ParticleSystem *psys; - particle_skip_object = render_override; + skip_object = render_override; for (psys = ob->particlesystem.first; psys; psys = psys->next) { /* Once we have found a psys which renders its emitter object, we are done. */ if (psys->part->draw & PART_DRAW_EMITTER) { - particle_skip_object = false; + skip_object = false; break; } } } } + if ((md = modifiers_findByType(ob, eModifierType_Smoke)) && (modifier_isEnabled(scene, md, eModifierMode_Realtime))) { + smd = (SmokeModifierData *)md; + + if (smd->domain) { + if (!v3d->transp && (dflag & DRAW_PICKING) == 0) { + if (!v3d->xray && !(ob->dtx & OB_DRAWXRAY)) { + /* object has already been drawn so skip drawing it */ + ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag); + return; + } + else if (v3d->xray) { + /* object has already been drawn so skip drawing it */ + ED_view3d_after_add(&v3d->afterdraw_xraytransp, base, dflag); + return; + } + } + } + } + + /* xray delay? */ if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* don't do xray in particle mode, need the z-buffer */ @@ -7908,13 +8222,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (dt >= OB_BOUNDBOX) { dtx = ob->dtx; if (ob->mode & OB_MODE_EDIT) { - // the only 2 extra drawtypes alowed in editmode + /* the only 2 extra drawtypes alowed in editmode */ dtx = dtx & (OB_DRAWWIRE | OB_TEXSPACE); } - } - if (!particle_skip_object) { + if (!skip_object) { /* draw outline for selected objects, mesh does itself */ if ((v3d->flag & V3D_SELECT_OUTLINE) && !render_override && ob->type != OB_MESH) { if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (dflag & DRAW_SCENESET) == 0) { @@ -7969,9 +8282,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) { empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); - -//XXX old animsys if (cu->path) -// curve_draw_speed(scene, ob); } break; case OB_MBALL: @@ -8090,7 +8400,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* code for new particle system */ if ((ob->particlesystem.first) && - (ob != scene->obedit)) + (ob != scene->obedit) && + !(ob->transflag & OB_IS_DUPLI_CACHE)) { ParticleSystem *psys; @@ -8107,14 +8418,16 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short view3d_cached_text_draw_begin(); for (psys = ob->particlesystem.first; psys; psys = psys->next) { - /* run this so that possible child particles get cached */ - if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) { - PTCacheEdit *edit = PE_create_current(scene, ob); - if (edit && edit->psys == psys) - draw_update_ptcache_edit(scene, ob, edit); + if (!(ob->mode & OB_MODE_HAIR_EDIT)) { + /* run this so that possible child particles get cached */ + if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) { + PTCacheEdit *edit = PE_create_current(scene, ob); + if (edit && edit->psys == psys) + draw_update_ptcache_edit(scene, ob, edit); + } + + draw_new_particle_system(scene, v3d, rv3d, base, psys, dt, dflag); } - - draw_new_particle_system(scene, v3d, rv3d, base, psys, dt, dflag); } invert_m4_m4(ob->imat, ob->obmat); view3d_cached_text_draw_end(v3d, ar, 0, NULL); @@ -8139,15 +8452,20 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short glMultMatrixf(ob->obmat); } } + + if (ob->mode & OB_MODE_HAIR_EDIT && is_obact) { + BMEditStrands *edit = BKE_editstrands_from_object(ob); + if (edit) { + draw_strands_edit_hair(scene, v3d, ar, edit); + } + } } /* draw code for smoke */ - if ((md = modifiers_findByType(ob, eModifierType_Smoke)) && (modifier_isEnabled(scene, md, eModifierMode_Realtime))) { - SmokeModifierData *smd = (SmokeModifierData *)md; - - // draw collision objects - if ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll) { + if (smd) { #if 0 + /* draw collision objects */ + if ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll) { SmokeCollSettings *scs = smd->coll; if (scs->points) { size_t i; @@ -8174,30 +8492,30 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short glDisable(GL_BLEND); glDepthMask(GL_TRUE); if (col) cpack(col); - } -#endif } +#endif /* only draw domains */ if (smd->domain) { SmokeDomainSettings *sds = smd->domain; - float p0[3], p1[3], viewnormal[3]; - BoundBox bb; + float viewnormal[3]; glLoadMatrixf(rv3d->viewmat); glMultMatrixf(ob->obmat); /* draw adaptive domain bounds */ - if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) { + if ((sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) && !render_override) { + float p0[3], p1[3]; + BoundBox bb; /* draw domain max bounds */ VECSUBFAC(p0, sds->p0, sds->cell_size, sds->adapt_res); VECADDFAC(p1, sds->p1, sds->cell_size, sds->adapt_res); BKE_boundbox_init_from_minmax(&bb, p0, p1); - draw_box(bb.vec); + draw_box(bb.vec, false); - /* draw base resolution bounds */ #if 0 + /* draw base resolution bounds */ BKE_boundbox_init_from_minmax(&bb, sds->p0, sds->p1); draw_box(bb.vec); #endif @@ -8205,16 +8523,16 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* don't show smoke before simulation starts, this could be made an option in the future */ if (smd->domain->fluid && CFRA >= smd->domain->point_cache[0]->startframe) { + float p0[3], p1[3]; - // get view vector - copy_v3_v3(viewnormal, rv3d->viewinv[2]); + /* get view vector */ invert_m4_m4(ob->imat, ob->obmat); - mul_mat3_m4_v3(ob->imat, viewnormal); + mul_v3_mat3_m4v3(viewnormal, ob->imat, rv3d->viewinv[2]); normalize_v3(viewnormal); /* set dynamic boundaries to draw the volume - * also scale cube to global space to equalize volume slicing on all axises - * (its scaled back before drawing) */ + * also scale cube to global space to equalize volume slicing on all axes + * (it's scaled back before drawing) */ p0[0] = (sds->p0[0] + sds->cell_size[0] * sds->res_min[0] + sds->obj_shift_f[0]) * fabsf(ob->size[0]); p0[1] = (sds->p0[1] + sds->cell_size[1] * sds->res_min[1] + sds->obj_shift_f[1]) * fabsf(ob->size[1]); p0[2] = (sds->p0[2] + sds->cell_size[2] * sds->res_min[2] + sds->obj_shift_f[2]) * fabsf(ob->size[2]); @@ -8298,7 +8616,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short view3d_cached_text_draw_add(zero, ob->id.name + 2, strlen(ob->id.name + 2), 10, 0, ob_wire_col); } } - /*if (dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp);*/ if ((dtx & OB_DRAWWIRE) && dt >= OB_SOLID) { if ((dflag & DRAW_CONSTCOLOR) == 0) { draw_wire_extra(scene, rv3d, ob, ob_wire_col); @@ -8347,7 +8664,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } /* object centers, need to be drawn in viewmat space for speed, but OK for picking select */ - if (!is_obact || !(ob->mode & OB_MODE_ALL_PAINT)) { + if (!is_obact || !(ob->mode & OB_MODE_ALL_BRUSH)) { int do_draw_center = -1; /* defines below are zero or positive... */ if (render_override) { @@ -8414,7 +8731,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_OBJECTSOLVER)) { /* special case for object solver and follow track constraints because they don't fill * constraint targets properly (design limitation -- scene is needed for their target - * but it can't be accessed from get_targets callvack) */ + * but it can't be accessed from get_targets callback) */ Object *camob = NULL; @@ -8439,7 +8756,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } } else { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon); if ((cti && cti->get_constraint_targets) && (curcon->flag & CONSTRAINT_EXPAND)) { ListBase targets = {NULL, NULL}; @@ -8671,7 +8988,7 @@ static void bbs_mesh_solid_verts(Scene *scene, Object *ob) static void bbs_mesh_solid_faces(Scene *scene, Object *ob) { DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); - Mesh *me = (Mesh *)ob->data; + Mesh *me = ob->data; glColor3ub(0, 0, 0); diff --git a/source/blender/editors/space_view3d/drawsimdebug.c b/source/blender/editors/space_view3d/drawsimdebug.c index 6113bfd4143..46320ba6763 100644 --- a/source/blender/editors/space_view3d/drawsimdebug.c +++ b/source/blender/editors/space_view3d/drawsimdebug.c @@ -29,28 +29,21 @@ * \ingroup spview3d */ -#include "MEM_guardedalloc.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_utildefines.h" #include "BLI_ghash.h" #include "BKE_effect.h" -#include "BKE_global.h" -#include "BKE_modifier.h" #include "view3d_intern.h" #include "BIF_gl.h" -#include "BIF_glutil.h" -#include "UI_resources.h" static void draw_sim_debug_elements(SimDebugData *debug_data, float imat[4][4]) { diff --git a/source/blender/editors/space_view3d/drawstrands.c b/source/blender/editors/space_view3d/drawstrands.c new file mode 100644 index 00000000000..af2e04ee3a7 --- /dev/null +++ b/source/blender/editors/space_view3d/drawstrands.c @@ -0,0 +1,520 @@ +/* + * ***** 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) 2014 by the Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Lukas Toenne + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/drawstrands.c + * \ingroup spview3d + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_utildefines.h" +#include "BLI_math.h" + +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_view3d_types.h" + +#include "BKE_editstrands.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_strands.h" + +#include "bmesh.h" + +#include "ED_screen.h" +#include "ED_types.h" + +#include "UI_resources.h" +#include "UI_interface_icons.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "GPU_draw.h" +#include "GPU_extensions.h" +#include "GPU_select.h" + +#include "view3d_intern.h" + +typedef struct StrandsDrawGLState { + GLint polygonmode[2]; +} StrandsDrawGLState; + +typedef enum StrandsShadeMode { + STRANDS_SHADE_FLAT, + STRANDS_SHADE_HAIR, +} StrandsShadeMode; + +static void draw_strands_begin(StrandsDrawGLState *state, short dflag) +{ + glGetIntegerv(GL_POLYGON_MODE, state->polygonmode); + glEnableClientState(GL_VERTEX_ARRAY); + + /* setup gl flags */ + glEnableClientState(GL_NORMAL_ARRAY); + + if ((dflag & DRAW_CONSTCOLOR) == 0) { +// if (part->draw_col == PART_DRAW_COL_MAT) +// glEnableClientState(GL_COLOR_ARRAY); + } + + glColor3f(1,1,1); + glEnable(GL_LIGHTING); +// glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); +// glEnable(GL_COLOR_MATERIAL); +} + +static void draw_strands_end(StrandsDrawGLState *state) +{ + /* restore & clean up */ +// if (part->draw_col == PART_DRAW_COL_MAT) +// glDisableClientState(GL_COLOR_ARRAY); + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + + glLineWidth(1.0f); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + + glPolygonMode(GL_FRONT, state->polygonmode[0]); + glPolygonMode(GL_BACK, state->polygonmode[1]); +} + +static void draw_strand_lines(Strands *strands, short dflag) +{ + const bool has_motion_state = strands->state; + StrandsDrawGLState gl_state; + StrandIterator it_strand; + + draw_strands_begin(&gl_state, dflag); + + for (BKE_strand_iter_init(&it_strand, strands); BKE_strand_iter_valid(&it_strand); BKE_strand_iter_next(&it_strand)) { + if (it_strand.tot <= 0) + continue; + + if (has_motion_state) { + glVertexPointer(3, GL_FLOAT, sizeof(StrandsMotionState), it_strand.state->co); + glNormalPointer(GL_FLOAT, sizeof(StrandsMotionState), it_strand.state->nor); + } + else { + glVertexPointer(3, GL_FLOAT, sizeof(StrandsVertex), it_strand.verts->co); + glNormalPointer(GL_FLOAT, sizeof(StrandsVertex), it_strand.verts->nor); + } + if ((dflag & DRAW_CONSTCOLOR) == 0) { +// if (part->draw_col == PART_DRAW_COL_MAT) { +// glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col); +// } + } + + glDrawArrays(GL_LINE_STRIP, 0, it_strand.curve->numverts); + } + + draw_strands_end(&gl_state); +} + +static void draw_strand_child_lines(StrandsChildren *children, short dflag) +{ + StrandsDrawGLState gl_state; + StrandChildIterator it_strand; + + draw_strands_begin(&gl_state, dflag); + + for (BKE_strand_child_iter_init(&it_strand, children); BKE_strand_child_iter_valid(&it_strand); BKE_strand_child_iter_next(&it_strand)) { + StrandsChildCurve *curve = it_strand.curve; + const int numverts = curve->cutoff < 0.0f ? curve->numverts : min_ii(curve->numverts, (int)ceilf(curve->cutoff) + 1); + + if (it_strand.tot <= 0) + continue; + + glVertexPointer(3, GL_FLOAT, sizeof(StrandsChildVertex), it_strand.verts->co); + glNormalPointer(GL_FLOAT, sizeof(StrandsChildVertex), it_strand.verts->nor); + + if ((dflag & DRAW_CONSTCOLOR) == 0) { +// if (part->draw_col == PART_DRAW_COL_MAT) { +// glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col); +// } + } + + + glDrawArrays(GL_LINE_STRIP, 0, numverts); + } + + draw_strands_end(&gl_state); +} + +void draw_strands(Scene *UNUSED(scene), View3D *UNUSED(v3d), ARegion *ar, Object *ob, Strands *strands, StrandsChildren *children, short dflag) +{ + RegionView3D *rv3d = ar->regiondata; + float imat[4][4]; + + invert_m4_m4(imat, rv3d->viewmatob); + +// glDepthMask(GL_FALSE); +// glEnable(GL_BLEND); + + glPushMatrix(); + + glLoadMatrixf(rv3d->viewmat); + glMultMatrixf(ob->obmat); + + if (children) + draw_strand_child_lines(children, dflag); + else + draw_strand_lines(strands, dflag); + + glPopMatrix(); + +// glDepthMask(GL_TRUE); +// glDisable(GL_BLEND); +} + +/* ------------------------------------------------------------------------- */ + +typedef struct StrandsDrawInfo { + bool has_zbuf; + bool use_zbuf_select; + + StrandsShadeMode shade_mode; + int select_mode; + + float col_base[4]; + float col_select[4]; +} StrandsDrawInfo; + +BLI_INLINE bool strands_use_normals(const StrandsDrawInfo *info) +{ + return ELEM(info->shade_mode, STRANDS_SHADE_HAIR); +} + +static void init_draw_info(StrandsDrawInfo *info, View3D *v3d, + StrandsShadeMode shade_mode, int select_mode) +{ + info->has_zbuf = v3d->zbuf; + info->use_zbuf_select = (v3d->flag & V3D_ZBUF_SELECT); + + info->shade_mode = shade_mode; + info->select_mode = select_mode; + + /* get selection theme colors */ + UI_GetThemeColor4fv(TH_VERTEX, info->col_base); + UI_GetThemeColor4fv(TH_VERTEX_SELECT, info->col_select); +} + +static void set_opengl_state_strands(const StrandsDrawInfo *info) +{ + if (!info->use_zbuf_select) + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + + if (ELEM(info->shade_mode, STRANDS_SHADE_HAIR)) { + glEnable(GL_LIGHTING); + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + glShadeModel(GL_SMOOTH); + } + else { + glDisable(GL_LIGHTING); + } + + glEnableClientState(GL_VERTEX_ARRAY); + if (strands_use_normals(info)) + glEnableClientState(GL_NORMAL_ARRAY); +} + +static void set_opengl_state_dots(const StrandsDrawInfo *info) +{ + if (!info->use_zbuf_select) + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + + glDisable(GL_LIGHTING); + + glEnableClientState(GL_VERTEX_ARRAY); + glPointSize(3.0); +} + +static void restore_opengl_state(const StrandsDrawInfo *info) +{ + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + glDisable(GL_BLEND); + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glShadeModel(GL_FLAT); + if (info->has_zbuf) + glEnable(GL_DEPTH_TEST); + glLineWidth(1.0f); + glPointSize(1.0); +} + +/* ------------------------------------------------------------------------- */ +/* strands */ + +static void setup_gpu_buffers_strands(BMEditStrands *edit, const StrandsDrawInfo *info) +{ + const size_t size_v3 = sizeof(float) * 3; + const size_t size_vertex = (strands_use_normals(info) ? 2*size_v3 : size_v3); + +// int totstrands = BM_strands_count(edit->bm); + int totvert = edit->bm->totvert; + int totedge = edit->bm->totedge; + + if (!edit->vertex_glbuf) + glGenBuffers(1, &edit->vertex_glbuf); + if (!edit->elem_glbuf) + glGenBuffers(1, &edit->elem_glbuf); + + glBindBuffer(GL_ARRAY_BUFFER, edit->vertex_glbuf); + glBufferData(GL_ARRAY_BUFFER, size_vertex * totvert, NULL, GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, edit->elem_glbuf); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * totedge * 2, NULL, GL_DYNAMIC_DRAW); + + glVertexPointer(3, GL_FLOAT, size_vertex, NULL); + if (strands_use_normals(info)) + glNormalPointer(GL_FLOAT, size_vertex, (GLubyte *)NULL + size_v3); +} + +static void unbind_gpu_buffers_strands(void) +{ + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + +static int write_gpu_buffers_strands(BMEditStrands *edit, const StrandsDrawInfo *info) +{ + const size_t size_v3 = sizeof(float) * 3; + const size_t size_vertex = (strands_use_normals(info) ? 2*size_v3 : size_v3); + + GLubyte *vertex_data; + unsigned int *elem_data; + BMVert *root, *v, *vprev; + BMIter iter, iter_strand; + int index, indexprev, index_edge; + int k; + + vertex_data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + elem_data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + if (!vertex_data || !elem_data) + return 0; + + BM_mesh_elem_index_ensure(edit->bm, BM_VERT); + + index_edge = 0; + BM_ITER_STRANDS(root, &iter, edit->bm, BM_STRANDS_OF_MESH) { + BM_ITER_STRANDS_ELEM_INDEX(v, &iter_strand, root, BM_VERTS_OF_STRAND, k) { + size_t offset_co; + + index = BM_elem_index_get(v); + + offset_co = index * size_vertex; + copy_v3_v3((float *)(vertex_data + offset_co), v->co); + + if (k > 0) { + if (strands_use_normals(info)) { + size_t offset_nor = offset_co + size_v3; + float nor[3]; + sub_v3_v3v3(nor, v->co, vprev->co); + normalize_v3(nor); + copy_v3_v3((float *)(vertex_data + offset_nor), nor); + + if (k == 1) { + /* define root normal: same as first segment */ + size_t offset_root_nor = indexprev * size_vertex + size_v3; + copy_v3_v3((float *)(vertex_data + offset_root_nor), nor); + } + } + + { + elem_data[index_edge + 0] = indexprev; + elem_data[index_edge + 1] = index; + index_edge += 2; + } + } + + vprev = v; + indexprev = index; + } + } + + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + + return index_edge; +} + +/* ------------------------------------------------------------------------- */ +/* dots */ + +static void setup_gpu_buffers_dots(BMEditStrands *edit, const StrandsDrawInfo *info, bool selected) +{ + const size_t size_v3 = sizeof(float) * 3; + const size_t size_vertex = size_v3; + BMesh *bm = edit->bm; + + BMVert *v; + BMIter iter; + int totvert; + + switch (info->select_mode) { + case HAIR_SELECT_STRAND: + totvert = 0; + break; + case HAIR_SELECT_VERTEX: + totvert = selected ? bm->totvertsel : bm->totvert - bm->totvertsel; + break; + case HAIR_SELECT_TIP: + totvert = 0; + BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test_bool(v, BM_ELEM_SELECT) != selected) + continue; + if (!BM_strands_vert_is_tip(v)) + continue; + + ++totvert; + } + break; + } + + if (totvert == 0) + return; + + if (!edit->dot_glbuf) + glGenBuffers(1, &edit->dot_glbuf); + + glBindBuffer(GL_ARRAY_BUFFER, edit->dot_glbuf); + glBufferData(GL_ARRAY_BUFFER, size_vertex * totvert, NULL, GL_DYNAMIC_DRAW); + + glVertexPointer(3, GL_FLOAT, size_vertex, NULL); +} + +static void unbind_gpu_buffers_dots(void) +{ + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +static int write_gpu_buffers_dots(BMEditStrands *edit, const StrandsDrawInfo *info, bool selected) +{ + const size_t size_v3 = sizeof(float) * 3; + const size_t size_vertex = size_v3; + + GLubyte *vertex_data; + BMVert *v; + BMIter iter; + int index_dot; + + if (info->select_mode == HAIR_SELECT_STRAND) + return 0; + + vertex_data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + if (!vertex_data) + return 0; + + BM_mesh_elem_index_ensure(edit->bm, BM_VERT); + + index_dot = 0; + switch (info->select_mode) { + case HAIR_SELECT_STRAND: + /* already exited, but keep the case for the compiler */ + break; + case HAIR_SELECT_VERTEX: + BM_ITER_MESH(v, &iter, edit->bm, BM_VERTS_OF_MESH) { + size_t offset_co; + + if (BM_elem_flag_test_bool(v, BM_ELEM_SELECT) != selected) + continue; + + offset_co = index_dot * size_vertex; + copy_v3_v3((float *)(vertex_data + offset_co), v->co); + ++index_dot; + } + break; + case HAIR_SELECT_TIP: + BM_ITER_MESH(v, &iter, edit->bm, BM_VERTS_OF_MESH) { + size_t offset_co; + + if (BM_elem_flag_test_bool(v, BM_ELEM_SELECT) != selected) + continue; + if (!BM_strands_vert_is_tip(v)) + continue; + + offset_co = index_dot * size_vertex; + copy_v3_v3((float *)(vertex_data + offset_co), v->co); + ++index_dot; + } + break; + } + + glUnmapBuffer(GL_ARRAY_BUFFER); + + return index_dot; +} + +/* ------------------------------------------------------------------------- */ + +static void draw_dots(BMEditStrands *edit, const StrandsDrawInfo *info, bool selected) +{ + int totelem; + + if (selected) + glColor3fv(info->col_select); + else + glColor3fv(info->col_base); + + setup_gpu_buffers_dots(edit, info, selected); + totelem = write_gpu_buffers_dots(edit, info, selected); + if (totelem > 0) + glDrawArrays(GL_POINTS, 0, totelem); +} + +void draw_strands_edit_hair(Scene *scene, View3D *v3d, ARegion *UNUSED(ar), BMEditStrands *edit) +{ + HairEditSettings *settings = &scene->toolsettings->hair_edit; + + StrandsDrawInfo info; + int totelem; + + init_draw_info(&info, v3d, STRANDS_SHADE_HAIR, settings->select_mode); + + set_opengl_state_strands(&info); + setup_gpu_buffers_strands(edit, &info); + totelem = write_gpu_buffers_strands(edit, &info); + if (totelem > 0) + glDrawElements(GL_LINES, totelem, GL_UNSIGNED_INT, NULL); + unbind_gpu_buffers_strands(); + + set_opengl_state_dots(&info); + draw_dots(edit, &info, false); + draw_dots(edit, &info, true); + unbind_gpu_buffers_dots(); + + restore_opengl_state(&info); +} diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index a220e1e39b0..2ee1241a2a4 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -48,8 +48,6 @@ #include "GPU_extensions.h" -#include "ED_mesh.h" - #include "view3d_intern.h" // own include struct GPUTexture; @@ -107,7 +105,8 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, float cor[3] = {1.0f, 1.0f, 1.0f}; int gl_depth = 0, gl_blend = 0; - int use_fire = (sds->active_fields & SM_ACTIVE_FIRE); + const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) != 0; + const float thickness = sds->display_thickness; /* draw slices of smoke is adapted from c++ code authored * by: Johannes Schmid and Ingemar Rask, 2006, johnny@grob.org */ @@ -137,76 +136,8 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, unsigned char *spec_data; float *spec_pixels; GPUTexture *tex_spec; - - /* Fragment program to calculate the view3d of smoke */ - /* using 4 textures, density, shadow, flame and flame spectrum */ - const char *shader_basic = - "!!ARBfp1.0\n" - "PARAM dx = program.local[0];\n" - "PARAM darkness = program.local[1];\n" - "PARAM render = program.local[2];\n" - "PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n" - "TEMP temp, shadow, flame, spec, value;\n" - "TEX temp, fragment.texcoord[0], texture[0], 3D;\n" - "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n" - "TEX flame, fragment.texcoord[0], texture[2], 3D;\n" - "TEX spec, flame.r, texture[3], 1D;\n" - /* calculate shading factor from density */ - "MUL value.r, temp.a, darkness.a;\n" - "MUL value.r, value.r, dx.r;\n" - "MUL value.r, value.r, f.r;\n" - "EX2 temp, -value.r;\n" - /* alpha */ - "SUB temp.a, 1.0, temp.r;\n" - /* shade colors */ - "MUL temp.r, temp.r, shadow.r;\n" - "MUL temp.g, temp.g, shadow.r;\n" - "MUL temp.b, temp.b, shadow.r;\n" - "MUL temp.r, temp.r, darkness.r;\n" - "MUL temp.g, temp.g, darkness.g;\n" - "MUL temp.b, temp.b, darkness.b;\n" - /* for now this just replace smoke shading if rendering fire */ - "CMP result.color, render.r, temp, spec;\n" - "END\n"; - - /* color shader */ - const char *shader_color = - "!!ARBfp1.0\n" - "PARAM dx = program.local[0];\n" - "PARAM darkness = program.local[1];\n" - "PARAM render = program.local[2];\n" - "PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};\n" - "TEMP temp, shadow, flame, spec, value;\n" - "TEX temp, fragment.texcoord[0], texture[0], 3D;\n" - "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n" - "TEX flame, fragment.texcoord[0], texture[2], 3D;\n" - "TEX spec, flame.r, texture[3], 1D;\n" - /* unpremultiply volume texture */ - "RCP value.r, temp.a;\n" - "MUL temp.r, temp.r, value.r;\n" - "MUL temp.g, temp.g, value.r;\n" - "MUL temp.b, temp.b, value.r;\n" - /* calculate shading factor from density */ - "MUL value.r, temp.a, darkness.a;\n" - "MUL value.r, value.r, dx.r;\n" - "MUL value.r, value.r, f.r;\n" - "EX2 value.r, -value.r;\n" - /* alpha */ - "SUB temp.a, 1.0, value.r;\n" - /* shade colors */ - "MUL temp.r, temp.r, shadow.r;\n" - "MUL temp.g, temp.g, shadow.r;\n" - "MUL temp.b, temp.b, shadow.r;\n" - "MUL temp.r, temp.r, value.r;\n" - "MUL temp.g, temp.g, value.r;\n" - "MUL temp.b, temp.b, value.r;\n" - /* for now this just replace smoke shading if rendering fire */ - "CMP result.color, render.r, temp, spec;\n" - "END\n"; - - GLuint prog; - - + GPUProgram *smoke_program; + int progtype = (sds->active_fields & SM_ACTIVE_COLORS) ? GPU_PROGRAM_SMOKE_COLORED : GPU_PROGRAM_SMOKE; float size[3]; if (!tex) { @@ -323,8 +254,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend); glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth); - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); + glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); /* find cube vertex that is closest to the viewer */ @@ -351,24 +281,17 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, // printf("i: %d\n", i); // printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]); - if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program")) { - glEnable(GL_FRAGMENT_PROGRAM_ARB); - glGenProgramsARB(1, &prog); - - glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog); - /* set shader */ - if (sds->active_fields & SM_ACTIVE_COLORS) - glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_color), shader_color); - else - glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_basic), shader_basic); + smoke_program = GPU_shader_get_builtin_program(progtype); + if (smoke_program) { + GPU_program_bind(smoke_program); /* cell spacing */ - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0); + GPU_program_parameter_4f(smoke_program, 0, dx, dx, dx, 1.0); /* custom parameter for smoke style (higher = thicker) */ if (sds->active_fields & SM_ACTIVE_COLORS) - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1.0, 1.0, 1.0, 10.0); + GPU_program_parameter_4f(smoke_program, 1, 1.0, 1.0, 1.0, 10.0 * thickness); else - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0); + GPU_program_parameter_4f(smoke_program, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0 * thickness); } else printf("Your gfx card does not support 3D View smoke drawing.\n"); @@ -448,7 +371,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, else glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, 1.0, 0.0, 0.0, 0.0); + GPU_program_parameter_4f(smoke_program, 2, 1.0, 0.0, 0.0, 0.0); glBegin(GL_POLYGON); glColor3f(1.0, 1.0, 1.0); for (i = 0; i < numpoints; i++) { @@ -468,7 +391,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, -1.0, 0.0, 0.0, 0.0); + GPU_program_parameter_4f(smoke_program, 2, -1.0, 0.0, 0.0, 0.0); glBegin(GL_POLYGON); glColor3f(1.0, 1.0, 1.0); for (i = 0; i < numpoints; i++) { @@ -501,10 +424,8 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, free(spec_data); free(spec_pixels); - if (GLEW_ARB_fragment_program) { - glDisable(GL_FRAGMENT_PROGRAM_ARB); - glDeleteProgramsARB(1, &prog); - } + if (smoke_program) + GPU_program_unbind(smoke_program); MEM_freeN(points); @@ -516,8 +437,6 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, if (gl_depth) { glEnable(GL_DEPTH_TEST); } - - glDepthMask(GL_TRUE); } #ifdef SMOKE_DEBUG_VELOCITY diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 447ceee5b13..e4f3e1d75ea 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -84,6 +84,8 @@ # include "BPY_extern.h" #endif +#include "DEG_depsgraph.h" + #include "view3d_intern.h" /* own include */ /* ******************** manage regions ********************* */ @@ -276,7 +278,7 @@ void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d) } #endif -static void view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar) +void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar) { RegionView3D *rv3d = ar->regiondata; @@ -307,7 +309,7 @@ void ED_view3d_shade_update(Main *bmain, Scene *scene, View3D *v3d, ScrArea *sa) for (ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->regiondata) - view3d_stop_render_preview(wm, ar); + ED_view3d_stop_render_preview(wm, ar); } } else if (scene->obedit != NULL && scene->obedit->type == OB_MESH) { @@ -354,7 +356,13 @@ static SpaceLink *view3d_new(const bContext *C) v3d->bundle_size = 0.2f; v3d->bundle_drawtype = OB_PLAINAXES; - + + /* stereo */ + v3d->stereo3d_camera = STEREO_3D_ID; + v3d->stereo3d_flag |= V3D_S3D_DISPPLANE; + v3d->stereo3d_convergence_alpha = 0.15f; + v3d->stereo3d_volume_alpha = 0.05f; + /* header */ ar = MEM_callocN(sizeof(ARegion), "header for view3d"); @@ -552,6 +560,9 @@ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar) keymap = WM_keymap_find(wm->defaultconf, "Particle", 0, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_find(wm->defaultconf, "Hair", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); + /* editfont keymap swallows all... */ keymap = WM_keymap_find(wm->defaultconf, "Font", 0, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); @@ -579,7 +590,7 @@ static void view3d_main_area_exit(wmWindowManager *wm, ARegion *ar) { RegionView3D *rv3d = ar->regiondata; - view3d_stop_render_preview(wm, ar); + ED_view3d_stop_render_preview(wm, ar); if (rv3d->gpuoffscreen) { GPU_offscreen_free(rv3d->gpuoffscreen); @@ -1097,7 +1108,8 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN (ob && (ob->mode == OB_MODE_TEXTURE_PAINT)) || (v3d->drawtype == OB_TEXTURE && (scene->gm.matmode == GAME_MAT_GLSL || - BKE_scene_use_new_shading_nodes(scene)))) + BKE_scene_use_new_shading_nodes(scene))) || + !DEG_depsgraph_use_legacy()) { ED_region_tag_redraw(ar); } @@ -1120,7 +1132,8 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN switch (wmn->data) { case ND_LIGHTING: if ((v3d->drawtype == OB_MATERIAL) || - (v3d->drawtype == OB_TEXTURE && (scene->gm.matmode == GAME_MAT_GLSL))) + (v3d->drawtype == OB_TEXTURE && (scene->gm.matmode == GAME_MAT_GLSL)) || + !DEG_depsgraph_use_legacy()) { ED_region_tag_redraw(ar); } @@ -1177,7 +1190,7 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN break; case NC_GPENCIL: - if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { + if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { ED_region_tag_redraw(ar); } break; @@ -1324,7 +1337,8 @@ static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa ED_region_tag_redraw(ar); break; case NC_BRUSH: - if (wmn->action == NA_EDITED) + /* NA_SELECTED is used on brush changes */ + if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) ED_region_tag_redraw(ar); break; case NC_SPACE: diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 88f43ab340f..1f8a69adba0 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -68,7 +68,6 @@ #include "RNA_access.h" #include "ED_armature.h" -#include "ED_gpencil.h" #include "ED_mesh.h" #include "ED_screen.h" @@ -200,7 +199,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float bool has_skinradius = false; PointerRNA data_ptr; - fill_vn_fl(median, NBR_TRANSFORM_PROPERTIES, 0.0f); + copy_vn_fl(median, NBR_TRANSFORM_PROPERTIES, 0.0f); tot = totedgedata = totcurvedata = totlattdata = totcurvebweight = 0; /* make sure we got storage */ diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index db29b08c5a9..5ccb16e514c 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -50,11 +50,13 @@ #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_endian_switch.h" +#include "BLI_threads.h" #include "BKE_anim.h" #include "BKE_camera.h" #include "BKE_context.h" #include "BKE_customdata.h" +#include "BKE_DerivedMesh.h" #include "BKE_image.h" #include "BKE_key.h" #include "BKE_main.h" @@ -99,6 +101,11 @@ #include "view3d_intern.h" /* own include */ +/* prototypes */ +static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar); +static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar, + float winmat[4][4], const char *viewname); + /* handy utility for drawing shapes in the viewport for arbitrary code. * could add lines and points too */ // #define DEBUG_DRAW @@ -207,7 +214,7 @@ void ED_view3d_clipping_enable(void) } } -static bool view3d_clipping_test(const float co[3], float clip[6][4]) +static bool view3d_clipping_test(const float co[3], const float clip[6][4]) { if (plane_point_side_v3(clip[0], co) > 0.0f) if (plane_point_side_v3(clip[1], co) > 0.0f) @@ -220,7 +227,7 @@ static bool view3d_clipping_test(const float co[3], float clip[6][4]) /* for 'local' ED_view3d_clipping_local must run first * then all comparisons can be done in localspace */ -bool ED_view3d_clipping_test(RegionView3D *rv3d, const float co[3], const bool is_local) +bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local) { return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip); } @@ -465,7 +472,7 @@ float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) return v3d->grid * ED_scene_grid_scale(scene, grid_unit); } -static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) +static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth) { float grid, grid_scale; unsigned char col_grid[3]; @@ -477,7 +484,8 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit); grid = gridlines * grid_scale; - glDepthMask(GL_FALSE); + if (!write_depth) + glDepthMask(GL_FALSE); UI_GetThemeColor3ubv(TH_GRID, col_grid); @@ -650,7 +658,7 @@ static void draw_rotation_guide(RegionView3D *rv3d) glEnable(GL_POINT_SMOOTH); glDepthMask(0); /* don't overwrite zbuf */ - if (rv3d->rot_angle != 0.f) { + if (rv3d->rot_angle != 0.0f) { /* -- draw rotation axis -- */ float scaled_axis[3]; const float scale = rv3d->dist; @@ -658,19 +666,21 @@ static void draw_rotation_guide(RegionView3D *rv3d) glBegin(GL_LINE_STRIP); - color[3] = 0.f; /* more transparent toward the ends */ + color[3] = 0.0f; /* more transparent toward the ends */ glColor4fv(color); add_v3_v3v3(end, o, scaled_axis); glVertex3fv(end); - // color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */ - // ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 +#if 0 + color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */ + /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */ +#endif color[3] = 0.5f; /* more opaque toward the center */ glColor4fv(color); glVertex3fv(o); - color[3] = 0.f; + color[3] = 0.0f; glColor4fv(color); sub_v3_v3v3(end, o, scaled_axis); glVertex3fv(end); @@ -681,14 +691,14 @@ static void draw_rotation_guide(RegionView3D *rv3d) #define ROT_AXIS_DETAIL 13 const float s = 0.05f * scale; - const float step = 2.f * (float)(M_PI / ROT_AXIS_DETAIL); + const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL); float angle; int i; float q[4]; /* rotate ring so it's perpendicular to axis */ const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f; if (!upright) { - const float up[3] = {0.f, 0.f, 1.f}; + const float up[3] = {0.0f, 0.0f, 1.0f}; float vis_angle, vis_axis[3]; cross_v3_v3v3(vis_axis, up, rv3d->rot_axis); @@ -699,7 +709,7 @@ static void draw_rotation_guide(RegionView3D *rv3d) color[3] = 0.25f; /* somewhat faint */ glColor4fv(color); glBegin(GL_LINE_LOOP); - for (i = 0, angle = 0.f; i < ROT_AXIS_DETAIL; ++i, angle += step) { + for (i = 0, angle = 0.0f; i < ROT_AXIS_DETAIL; ++i, angle += step) { float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f}; if (!upright) { @@ -725,12 +735,12 @@ static void draw_rotation_guide(RegionView3D *rv3d) glVertex3fv(o); glEnd(); - /* find screen coordinates for rotation center, then draw pretty icon */ #if 0 + /* find screen coordinates for rotation center, then draw pretty icon */ mul_m4_v3(rv3d->persinv, rot_center); UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN); -#endif /* ^^ just playing around, does not work */ +#endif glDisable(GL_BLEND); glDisable(GL_POINT_SMOOTH); @@ -949,8 +959,9 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info)); } -static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, - rctf *r_viewborder, const bool no_shift, const bool no_zoom) +static void view3d_camera_border( + const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d, + rctf *r_viewborder, const bool no_shift, const bool no_zoom) { CameraParams params; rctf rect_view, rect_camera; @@ -983,7 +994,9 @@ static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionV r_viewborder->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy; } -void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, float r_size[2]) +void ED_view3d_calc_camera_border_size( + const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d, + float r_size[2]) { rctf viewborder; @@ -992,8 +1005,9 @@ void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, R r_size[1] = BLI_rctf_size_y(&viewborder); } -void ED_view3d_calc_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, - rctf *r_viewborder, const bool no_shift) +void ED_view3d_calc_camera_border( + const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d, + rctf *r_viewborder, const bool no_shift) { view3d_camera_border(scene, ar, v3d, rv3d, r_viewborder, no_shift, false); } @@ -1314,12 +1328,12 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d) /* do nothing */ } else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) && - v3d->drawtype > OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT)) + V3D_IS_ZBUF(v3d)) { /* do nothing */ } - else if (scene->obedit && v3d->drawtype > OB_WIRE && - (v3d->flag & V3D_ZBUF_SELECT)) + else if (scene->obedit && + V3D_IS_ZBUF(v3d)) { /* do nothing */ } @@ -1441,14 +1455,23 @@ static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); } -void view3d_validate_backbuf(ViewContext *vc) +void ED_view3d_backbuf_validate(ViewContext *vc) { if (vc->v3d->flag & V3D_INVALID_BACKBUF) backdrawview3d(vc->scene, vc->ar, vc->v3d); } +/** + * allow for small values [0.5 - 2.5], + * and large values, FLT_MAX by clamping by the area size + */ +int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) +{ + return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); +} + /* samples a single pixel (copied from vpaint) */ -unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y) +unsigned int ED_view3d_backbuf_sample(ViewContext *vc, int x, int y) { unsigned int col; @@ -1456,7 +1479,7 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y) return 0; } - view3d_validate_backbuf(vc); + ED_view3d_backbuf_validate(vc); view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); glReadBuffer(GL_BACK); @@ -1469,7 +1492,7 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y) } /* reads full rect, converts indices */ -ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) +ImBuf *ED_view3d_backbuf_read(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) { unsigned int *dr, *rd; struct ImBuf *ibuf, *ibuf1; @@ -1477,17 +1500,18 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, short xminc, yminc, xmaxc, ymaxc, xs, ys; /* clip */ - if (xmin < 0) xminc = 0; else xminc = xmin; - if (xmax >= vc->ar->winx) xmaxc = vc->ar->winx - 1; else xmaxc = xmax; - if (xminc > xmaxc) return NULL; + xminc = max_ii(xmin, 0); + yminc = max_ii(ymin, 0); + xmaxc = min_ii(xmax, vc->ar->winx - 1); + ymaxc = min_ii(ymax, vc->ar->winy - 1); + + if (UNLIKELY((xminc > xmaxc) || (yminc > ymaxc))) { + return NULL; + } - if (ymin < 0) yminc = 0; else yminc = ymin; - if (ymax >= vc->ar->winy) ymaxc = vc->ar->winy - 1; else ymaxc = ymax; - if (yminc > ymaxc) return NULL; - ibuf = IMB_allocImBuf((xmaxc - xminc + 1), (ymaxc - yminc + 1), 32, IB_rect); - view3d_validate_backbuf(vc); + ED_view3d_backbuf_validate(vc); view3d_opengl_read_pixels(vc->ar, xminc, yminc, @@ -1527,23 +1551,21 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, } /* smart function to sample a rect spiralling outside, nice for backbuf selection */ -unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int size, - unsigned int min, unsigned int max, float *r_dist, short strict, - void *handle, bool (*indextest)(void *handle, unsigned int index)) +unsigned int ED_view3d_backbuf_sample_rect( + ViewContext *vc, const int mval[2], int size, + unsigned int min, unsigned int max, float *r_dist) { struct ImBuf *buf; - unsigned int *bufmin, *bufmax, *tbuf; + const unsigned int *bufmin, *bufmax, *tbuf; int minx, miny; int a, b, rc, nr, amount, dirvec[4][2]; - int distance = 0; unsigned int index = 0; - bool indexok = false; amount = (size - 1) / 2; minx = mval[0] - (amount + 1); miny = mval[1] - (amount + 1); - buf = view3d_read_backbuf(vc, minx, miny, minx + size - 1, miny + size - 1); + buf = ED_view3d_backbuf_read(vc, minx, miny, minx + size - 1, miny + size - 1); if (!buf) return 0; rc = 0; @@ -1561,21 +1583,19 @@ unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int for (nr = 1; nr <= size; nr++) { for (a = 0; a < 2; a++) { - for (b = 0; b < nr; b++, distance++) { - if (*tbuf && *tbuf >= min && *tbuf < max) { /* we got a hit */ - if (strict) { - indexok = indextest(handle, *tbuf - min + 1); - if (indexok) { - *r_dist = sqrtf((float)distance); - index = *tbuf - min + 1; - goto exit; - } - } - else { - *r_dist = sqrtf((float)distance); /* XXX, this distance is wrong - */ - index = *tbuf - min + 1; /* messy yah, but indices start at 1 */ - goto exit; - } + for (b = 0; b < nr; b++) { + if (*tbuf && *tbuf >= min && *tbuf < max) { + /* we got a hit */ + + /* get x,y pixel coords from the offset + * (manhatten distance in keeping with other screen-based selection) */ + *r_dist = (float)( + abs(((int)(tbuf - buf->rect) % size) - (size / 2)) + + abs(((int)(tbuf - buf->rect) / size) - (size / 2))); + + /* indices start at 1 here */ + index = (*tbuf - min) + 1; + goto exit; } tbuf += (dirvec[rc][0] + dirvec[rc][1]); @@ -1597,6 +1617,26 @@ exit: /* ************************************************************* */ +static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser) +{ + if ((ima->flag & IMA_IS_STEREO)) { + iuser->flag |= IMA_SHOW_STEREO; + + if ((scene->r.scemode & R_MULTIVIEW) == 0) { + iuser->multiview_eye = STEREO_LEFT_ID; + } + else if (v3d->stereo3d_camera != STEREO_3D_ID) { + /* show only left or right camera */ + iuser->multiview_eye = v3d->stereo3d_camera; + } + + BKE_image_multiview_index(ima, iuser); + } + else { + iuser->flag &= ~IMA_SHOW_STEREO; + } +} + static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, const bool do_foreground, const bool do_camera_frame) { @@ -1620,6 +1660,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, ImBuf *ibuf = NULL, *freeibuf, *releaseibuf; void *lock; + rctf clip_rect; Image *ima = NULL; MovieClip *clip = NULL; @@ -1639,6 +1680,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, ibuf = NULL; /* frame is out of range, dont show */ } else { + view3d_stereo_bgpic_setup(scene, v3d, ima, &bgpic->iuser); ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, &lock); releaseibuf = ibuf; } @@ -1782,8 +1824,12 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, } /* complete clip? */ + BLI_rctf_init(&clip_rect, x1, x2, y1, y2); + if (bgpic->rotation) { + BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation); + } - if (x2 < 0 || y2 < 0 || x1 > ar->winx || y1 > ar->winy) { + if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) { if (freeibuf) IMB_freeImBuf(freeibuf); if (releaseibuf) @@ -1830,9 +1876,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, ED_region_pixelspace(ar); glTranslatef(centx, centy, 0.0); - if (rv3d->persp != RV3D_CAMOB) { - glRotatef(RAD2DEGF(-bgpic->rotation), 0.0f, 0.0f, 1.0f); - } + glRotatef(RAD2DEGF(-bgpic->rotation), 0.0f, 0.0f, 1.0f); if (bgpic->flag & V3D_BGPIC_FLIP_X) { zoomx *= -1.0f; @@ -2063,6 +2107,27 @@ int dupli_ob_sort(void *arg1, void *arg2) } #endif +static void draw_dupli_object(Scene *scene, ARegion *ar, View3D *v3d, + Base *base, DupliObject *UNUSED(dob), DupliObjectData *dob_data, + short dflag, bool draw_dupli_strands) +{ + draw_object(scene, ar, v3d, base, dflag); + + if (dob_data) { + + /* draw strands only when not editing */ + if (draw_dupli_strands) { + DupliObjectDataStrands *link; + + for (link = dob_data->strands.first; link; link = link->next) { + struct Strands *strands = link->strands; + struct StrandsChildren *children = link->strands_children; + + draw_strands(scene, v3d, ar, base->object, strands, children, dflag); + } + } + } +} static DupliObject *dupli_step(DupliObject *dob) { @@ -2084,6 +2149,7 @@ static void draw_dupli_objects_color( GLuint displist = 0; unsigned char color_rgb[3]; const short dflag_dupli = dflag | DRAW_CONSTCOLOR; + const bool draw_dupli_strands = !(base->object->mode & OB_MODE_HAIR_EDIT); short transflag; bool use_displist = false; /* -1 is initialize */ char dt; @@ -2101,17 +2167,22 @@ static void draw_dupli_objects_color( UI_GetThemeColorBlend3ubv(color, TH_BACK, 0.5f, color_rgb); } - tbase.flag = OB_FROMDUPLI | base->flag; + tbase.flag |= OB_FROMDUPLI; lb = object_duplilist(G.main->eval_ctx, scene, base->object); // BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */ - apply_data = duplilist_apply(base->object, lb); + apply_data = duplilist_apply(base->object, scene, lb); dob = dupli_step(lb->first); if (dob) dob_next = dupli_step(dob->next); for (; dob; dob_prev = dob, dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) { + /* for restoring after override */ + DupliObjectData *dob_data = NULL; + DerivedMesh *store_final_dm; + tbase.object = dob->ob; + store_final_dm = dob->ob->derivedFinal; /* Make sure lod is updated from dupli's position */ @@ -2148,6 +2219,21 @@ static void draw_dupli_objects_color( glColor3ubv(color_rgb); } + /* override final DM */ + bb_tmp = NULL; + tbase.object->transflag &= ~OB_IS_DUPLI_CACHE; + if (base->object->dup_cache) { + dob_data = BKE_dupli_cache_find_data(base->object->dup_cache, tbase.object); + if (dob_data && dob_data->dm) { + tbase.object->transflag |= OB_IS_DUPLI_CACHE; + + tbase.object->derivedFinal = dob_data->dm; + bb_tmp = &dob_data->bb; + } + } + if (!bb_tmp) + bb_tmp = BKE_object_boundbox_get(dob->ob); + /* generate displist, test for new object */ if (dob_prev && dob_prev->ob != dob->ob) { if (use_displist == true) @@ -2156,7 +2242,7 @@ static void draw_dupli_objects_color( use_displist = false; } - if ((bb_tmp = BKE_object_boundbox_get(dob->ob))) { + if (bb_tmp) { bb = *bb_tmp; /* must make a copy */ testbb = true; } @@ -2194,7 +2280,7 @@ static void draw_dupli_objects_color( displist = glGenLists(1); glNewList(displist, GL_COMPILE); - draw_object(scene, ar, v3d, &tbase, dflag_dupli); + draw_dupli_object(scene, ar, v3d, &tbase, dob, dob_data, dflag_dupli, draw_dupli_strands); glEndList(); use_displist = true; @@ -2210,8 +2296,24 @@ static void draw_dupli_objects_color( } else { copy_m4_m4(dob->ob->obmat, dob->mat); - draw_object(scene, ar, v3d, &tbase, dflag_dupli); + draw_dupli_object(scene, ar, v3d, &tbase, dob, dob_data, dflag_dupli, draw_dupli_strands); + } + } + + /* restore final DM */ + if (tbase.object->transflag & OB_IS_DUPLI_CACHE) { + DerivedMesh *cur = tbase.object->derivedFinal; + + /* in some cases drawing code can recreate the derivedFinal, + * make sure we free those first before restoring + */ + if (cur && cur != dob_data->dm) { + cur->needsFree = 1; + cur->release(cur); } + + tbase.object->transflag &= ~OB_IS_DUPLI_CACHE; + tbase.object->derivedFinal = store_final_dm; } tbase.object->dt = dt; @@ -2551,13 +2653,14 @@ static void gpu_render_lamp_update(Scene *scene, View3D *v3d, Object *ob, Object } } -static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) +static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d) { ListBase shadows; View3DShadow *shadow; Scene *sce_iter; Base *base; Object *ob; + World *world = scene->world; SceneRenderLayer *srl = v3d->scenelock ? BLI_findlink(&scene->r.layers, scene->r.actlay) : NULL; BLI_listbase_clear(&shadows); @@ -2613,7 +2716,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) ED_view3d_draw_offscreen( scene, v3d, &ar, winsize, winsize, viewmat, winmat, false, false, true, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); GPU_lamp_shadow_buffer_unbind(shadow->lamp); v3d->drawtype = drawtype; @@ -2622,11 +2725,19 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) } BLI_freelistN(&shadows); + + /* update world values */ + if (world) { + GPU_mist_update_enable(world->mode & WO_MIST); + GPU_mist_update_values(world->mistype, world->miststa, world->mistdist, world->misi, &world->horr); + GPU_horizon_update_color(&world->horr); + GPU_ambient_update_color(&world->ambr); + } } /* *********************** customdata **************** */ -CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d) +CustomDataMask ED_view3d_datamask(const Scene *scene, const View3D *v3d) { CustomDataMask mask = 0; @@ -2652,16 +2763,16 @@ CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d) } /* goes over all modes and view3d settings */ -CustomDataMask ED_view3d_screen_datamask(bScreen *screen) +CustomDataMask ED_view3d_screen_datamask(const bScreen *screen) { - Scene *scene = screen->scene; + const Scene *scene = screen->scene; CustomDataMask mask = CD_MASK_BAREMESH; - ScrArea *sa; + const ScrArea *sa; /* check if we need tfaces & mcols due to view mode */ for (sa = screen->areabase.first; sa; sa = sa->next) { if (sa->spacetype == SPACE_VIEW3D) { - mask |= ED_view3d_datamask(scene, (View3D *)sa->spacedata.first); + mask |= ED_view3d_datamask(scene, sa->spacedata.first); } } @@ -2747,7 +2858,7 @@ static void view3d_draw_objects( const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0; const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO); /* only draw grids after in solid modes, else it hovers over mesh wires */ - const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE); + const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx; bool do_composite_xray = false; bool xrayclear = true; @@ -2796,8 +2907,8 @@ static void view3d_draw_objects( glMatrixMode(GL_MODELVIEW); glLoadMatrixf(rv3d->viewmat); } - else { - drawfloor(scene, v3d, grid_unit); + else if (!draw_grids_after) { + drawfloor(scene, v3d, grid_unit, true); } } @@ -2879,7 +2990,7 @@ static void view3d_draw_objects( /* perspective floor goes last to use scene depth and avoid writing to depth buffer */ if (draw_grids_after) { - drawfloor(scene, v3d, grid_unit); + drawfloor(scene, v3d, grid_unit, false); } /* must be before xray draw which clears the depth buffer */ @@ -2948,39 +3059,57 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d) { /* shadow buffers, before we setup matrices */ if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) - gpu_update_lamps_shadows(scene, v3d); + gpu_update_lamps_shadows_world(scene, v3d); } /* * Function to clear the view */ -static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar, bool force) +static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar) { const bool is_wire_color = V3D_IS_WIRECOLOR(scene, v3d); - - /* clear background */ - if (scene->world && ((v3d->flag3 & V3D_SHOW_WORLD) || force)) { - float alpha = (force) ? 1.0f : 0.0f; + + if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) { bool glsl = GPU_glsl_support() && BKE_scene_use_new_shading_nodes(scene) && scene->world->nodetree && scene->world->use_nodes; if (glsl) { RegionView3D *rv3d = ar->regiondata; GPUMaterial *gpumat = GPU_material_world(scene, scene->world); + bool material_not_bound; /* calculate full shader for background */ GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0)); + material_not_bound = !GPU_material_bound(gpumat); + + if (material_not_bound) { + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + } + glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); glShadeModel(GL_SMOOTH); - glBegin(GL_QUADS); + glBegin(GL_TRIANGLE_STRIP); glVertex3f(-1.0, -1.0, 1.0); glVertex3f(1.0, -1.0, 1.0); - glVertex3f(1.0, 1.0, 1.0); glVertex3f(-1.0, 1.0, 1.0); + glVertex3f(1.0, 1.0, 1.0); glEnd(); glShadeModel(GL_FLAT); + if (material_not_bound) { + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } + GPU_material_unbind(gpumat); glDepthFunc(GL_LEQUAL); @@ -3073,7 +3202,7 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar, bool interp_v3_v3v3(col_fl, col_hor, col_zen, col_fac); rgb_float_to_uchar(col_ub, col_fl); - col_ub[3] = alpha * 255; + col_ub[3] = 255; } } @@ -3114,7 +3243,7 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar, bool IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings, &scene->display_settings); - glClearColor(col_hor[0], col_hor[1], col_hor[2], alpha); + glClearColor(col_hor[0], col_hor[1], col_hor[2], 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (is_wire_color) { @@ -3167,7 +3296,7 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar, bool float col[3]; UI_GetThemeColor3fv(TH_HIGH_GRAD, col); - UI_ThemeClearColor(TH_HIGH_GRAD); + UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (is_wire_color) { @@ -3185,7 +3314,8 @@ void ED_view3d_draw_offscreen( float viewmat[4][4], float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp, GPUOffScreen *ofs, - GPUFX *fx, GPUFXSettings *fx_settings) + GPUFX *fx, GPUFXSettings *fx_settings, + const char *viewname) { struct bThemeState theme_state; int bwinx, bwiny; @@ -3220,16 +3350,29 @@ void ED_view3d_draw_offscreen( } /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */ - view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat); + if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera) + view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname); + else + view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat); /* framebuffer fx needed, we need to draw offscreen first */ if (v3d->fx_settings.fx_flag && fx) { + GPUSSAOSettings *ssao = NULL; + + if (v3d->drawtype < OB_SOLID) { + ssao = v3d->fx_settings.ssao; + v3d->fx_settings.ssao = NULL; + } + do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings); + + if (ssao) + v3d->fx_settings.ssao = ssao; } /* clear opengl buffers */ if (do_sky) { - view3d_main_area_clear(scene, v3d, ar, true); + view3d_main_area_clear(scene, v3d, ar); } else { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); @@ -3274,13 +3417,16 @@ void ED_view3d_draw_offscreen( /* utility func for ED_view3d_draw_offscreen */ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey, unsigned int flag, - bool draw_background, int alpha_mode, char err_out[256]) + bool draw_background, int alpha_mode, const char *viewname, char err_out[256]) { RegionView3D *rv3d = ar->regiondata; ImBuf *ibuf; GPUOffScreen *ofs; bool draw_sky = (alpha_mode == R_ADDSKY) && v3d && (v3d->flag3 & V3D_SHOW_WORLD); + if (UNLIKELY(v3d == NULL)) + return NULL; + /* state changes make normal drawing go weird otherwise */ glPushAttrib(GL_LIGHTING_BIT); @@ -3298,14 +3444,15 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in /* render 3d view */ if (rv3d->persp == RV3D_CAMOB && v3d->camera) { CameraParams params; - GPUFXSettings fx_settings = {0}; - Object *camera = v3d->camera; + GPUFXSettings fx_settings = {NULL}; + Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); BKE_camera_params_init(¶ms); /* fallback for non camera objects */ params.clipsta = v3d->near; params.clipend = v3d->far; - BKE_camera_params_from_object(¶ms, v3d->camera); + BKE_camera_params_from_object(¶ms, camera); + BKE_camera_multiview_params(&scene->r, ¶ms, camera, viewname); BKE_camera_params_compute_viewplane(¶ms, sizex, sizey, scene->r.xasp, scene->r.yasp); BKE_camera_params_compute_matrix(¶ms); @@ -3314,13 +3461,13 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in ED_view3d_draw_offscreen( scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background, draw_sky, !params.is_ortho, - ofs, NULL, &fx_settings); + ofs, NULL, &fx_settings, viewname); } else { ED_view3d_draw_offscreen( scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background, draw_sky, true, - ofs, NULL, NULL); + ofs, NULL, NULL, viewname); } /* read in pixels & stamp */ @@ -3345,7 +3492,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in /* creates own 3d views, used by the sequencer */ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int width, int height, unsigned int flag, int drawtype, - bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, char err_out[256]) + bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, + const char *viewname, char err_out[256]) { View3D v3d = {NULL}; ARegion ar = {NULL}; @@ -3375,9 +3523,11 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w { CameraParams params; + Object *camera = BKE_camera_multiview_render(scene, v3d.camera, viewname); BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, v3d.camera); + BKE_camera_params_from_object(¶ms, camera); + BKE_camera_multiview_params(&scene->r, ¶ms, camera, viewname); BKE_camera_params_compute_viewplane(¶ms, width, height, scene->r.xasp, scene->r.yasp); BKE_camera_params_compute_matrix(¶ms); @@ -3391,7 +3541,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w invert_m4_m4(rv3d.persinv, rv3d.viewinv); return ED_view3d_draw_offscreen_imbuf(scene, &v3d, &ar, width, height, flag, - draw_background, alpha_mode, err_out); + draw_background, alpha_mode, viewname, err_out); // seq_view3d_cb(scene, cfra, render_size, seqrectx, seqrecty); } @@ -3596,6 +3746,103 @@ static void view3d_main_area_draw_engine_info(View3D *v3d, RegionView3D *rv3d, A ED_region_info_draw(ar, rv3d->render_engine->text, 1, fill_color); } +static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d) +{ + wmWindow *win = CTX_wm_window(C); + + if ((scene->r.scemode & R_MULTIVIEW) == 0) + return false; + + if (WM_stereo3d_enabled(win, true) == false) + return false; + + if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) + return false; + + if (scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) { + if (v3d->stereo3d_camera == STEREO_MONO_ID) + return false; + + return BKE_scene_multiview_is_stereo3d(&scene->r); + } + + return true; +} + +/* setup the view and win matrices for the multiview cameras + * + * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called + * we have no winmatrix (i.e., projection matrix) defined at that time. + * Since the camera and the camera shift are needed for the winmat calculation + * we do a small hack to replace it temporarily so we don't need to change the + * view3d)main_area_setup_view() code to account for that. + */ +static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar) +{ + bool is_left; + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + const char *viewname; + + /* show only left or right camera */ + if (v3d->stereo3d_camera != STEREO_3D_ID) + v3d->multiview_eye = v3d->stereo3d_camera; + + is_left = v3d->multiview_eye == STEREO_LEFT_ID; + viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID]; + + /* update the viewport matrices with the new camera */ + if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { + Camera *data; + float viewmat[4][4]; + float shiftx; + + data = (Camera *)v3d->camera->data; + shiftx = data->shiftx; + + BLI_lock_thread(LOCK_VIEW3D); + data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname); + + BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); + view3d_main_area_setup_view(scene, v3d, ar, viewmat, NULL); + + data->shiftx = shiftx; + BLI_unlock_thread(LOCK_VIEW3D); + } + else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ + float viewmat[4][4]; + Object *view_ob = v3d->camera; + Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); + + BLI_lock_thread(LOCK_VIEW3D); + v3d->camera = camera; + + BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); + view3d_main_area_setup_view(scene, v3d, ar, viewmat, NULL); + + v3d->camera = view_ob; + BLI_unlock_thread(LOCK_VIEW3D); + } +} + +static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar, + float winmat[4][4], const char *viewname) +{ + /* update the viewport matrices with the new camera */ + if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { + float viewmat[4][4]; + const bool is_left = STREQ(viewname, STEREO_LEFT_NAME); + + BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); + view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat); + } + else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ + float viewmat[4][4]; + Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); + + BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); + view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat); + } +} #ifdef WITH_GAMEENGINE static void update_lods(Scene *scene, float camera_pos[3]) @@ -3622,16 +3869,19 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3 /* shadow buffers, before we setup matrices */ if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) - gpu_update_lamps_shadows(scene, v3d); - + gpu_update_lamps_shadows_world(scene, v3d); + /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */ if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) { rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE; GPU_default_lights(); } - /* setup view matrices */ - view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL); + /* setup the view matrix */ + if (view3d_stereo3d_active(C, scene, v3d, rv3d)) + view3d_stereo3d_setup(scene, v3d, ar); + else + view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL); rv3d->rflag &= ~RV3D_IS_GAME_ENGINE; #ifdef WITH_GAMEENGINE @@ -3644,7 +3894,7 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3 #endif /* framebuffer fx needed, we need to draw offscreen first */ - if (v3d->fx_settings.fx_flag) { + if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) { GPUFXSettings fx_settings; BKE_screen_gpu_fx_validate(&v3d->fx_settings); fx_settings = v3d->fx_settings; @@ -3656,11 +3906,12 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3 else { fx_settings.dof = NULL; } + do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings); } /* clear the background */ - view3d_main_area_clear(scene, v3d, ar, false); + view3d_main_area_clear(scene, v3d, ar); /* enables anti-aliasing for 3D view drawing */ if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) { @@ -3715,7 +3966,7 @@ static bool is_cursor_visible(Scene *scene) else if (ob->mode & OB_MODE_TEXTURE_PAINT) { const Paint *p = BKE_paint_get_active(scene); - if (p && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) { + if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) { if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) { return true; } @@ -3785,7 +4036,7 @@ static void view3d_main_area_draw_info(const bContext *C, Scene *scene, if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { wmWindowManager *wm = CTX_wm_manager(C); - if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_playing(wm)) { + if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) { ED_scene_draw_fps(scene, &rect); } else if (U.uiflag & USER_SHOW_VIEWPORTNAME) { diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 39541c108ff..b8add39b0e6 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -28,7 +28,6 @@ * \ingroup spview3d */ - #include <string.h> #include <stdio.h> #include <math.h> @@ -38,7 +37,6 @@ #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "DNA_camera_types.h" #include "MEM_guardedalloc.h" @@ -75,7 +73,6 @@ #include "ED_transform.h" #include "ED_mesh.h" #include "ED_view3d.h" -#include "ED_sculpt.h" #include "UI_resources.h" @@ -83,7 +80,7 @@ #include "view3d_intern.h" /* own include */ -bool ED_view3d_offset_lock_check(struct View3D *v3d, struct RegionView3D *rv3d) +bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d) { return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre); } @@ -103,7 +100,7 @@ static bool view3d_operator_offset_lock_check(bContext *C, wmOperator *op) /* ********************** view3d_edit: view manipulations ********************* */ -bool ED_view3d_camera_lock_check(View3D *v3d, RegionView3D *rv3d) +bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d) { return ((v3d->camera) && (v3d->camera->id.lib == NULL) && @@ -520,6 +517,7 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip) typedef struct ViewOpsData { /* context pointers (assigned by viewops_data_alloc) */ + Scene *scene; ScrArea *sa; ARegion *ar; View3D *v3d; @@ -592,6 +590,7 @@ static void viewops_data_alloc(bContext *C, wmOperator *op) /* store data */ op->customdata = vod; + vod->scene = CTX_data_scene(C); vod->sa = CTX_wm_area(C); vod->ar = CTX_wm_region(C); vod->v3d = vod->sa->spacedata.first; @@ -1313,7 +1312,7 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) ot->cancel = viewrotate_cancel; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; } /** \name NDOF Utility Functions @@ -2056,7 +2055,7 @@ void VIEW3D_OT_move(wmOperatorType *ot) ot->cancel = viewmove_cancel; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; } /* ************************ viewzoom ******************************** */ @@ -2096,16 +2095,63 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom"); } -static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) +static void view_zoom_mouseloc_camera( + Scene *scene, View3D *v3d, + ARegion *ar, float dfac, int mx, int my) { RegionView3D *rv3d = ar->regiondata; + const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom); + const float zoomfac_new = CLAMPIS(zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR); + const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new); + + + if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { + float zoomfac_px; + rctf camera_frame_old; + rctf camera_frame_new; + + const float pt_src[2] = {mx, my}; + float pt_dst[2]; + float delta_px[2]; + + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_old, false); + BLI_rctf_translate(&camera_frame_old, ar->winrct.xmin, ar->winrct.ymin); + + rv3d->camzoom = camzoom_new; + CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); + + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_new, false); + BLI_rctf_translate(&camera_frame_new, ar->winrct.xmin, ar->winrct.ymin); + + BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src); + sub_v2_v2v2(delta_px, pt_dst, pt_src); + + /* translate the camera offset using pixel space delta + * mapped back to the camera (same logic as panning in camera view) */ + zoomfac_px = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 2.0f; + + rv3d->camdx += delta_px[0] / (ar->winx * zoomfac_px); + rv3d->camdy += delta_px[1] / (ar->winy * zoomfac_px); + CLAMP(rv3d->camdx, -1.0f, 1.0f); + CLAMP(rv3d->camdy, -1.0f, 1.0f); + } + else { + rv3d->camzoom = camzoom_new; + CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); + } +} + +static void view_zoom_mouseloc_3d(ARegion *ar, float dfac, int mx, int my) +{ + RegionView3D *rv3d = ar->regiondata; + const float dist_new = rv3d->dist * dfac; if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { float dvec[3]; float tvec[3]; float tpos[3]; float mval_f[2]; - float new_dist; + float zfac; negate_v3_v3(tpos, rv3d->ofs); @@ -2122,105 +2168,133 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) negate_v3(tvec); /* Offset to target position and dolly */ - new_dist = rv3d->dist * dfac; - copy_v3_v3(rv3d->ofs, tvec); - rv3d->dist = new_dist; + rv3d->dist = dist_new; /* Calculate final offset */ madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac); } else { - rv3d->dist *= dfac; + rv3d->dist = dist_new; } } - -static void viewzoom_apply(ViewOpsData *vod, const int xy[2], const short viewzoom, const short zoom_invert) +static float viewzoom_scale_value( + const rcti *winrct, + const short viewzoom, + const bool zoom_invert, const bool zoom_invert_force, + const int xy[2], const int xy_orig[2], + const float val, const float val_orig, + double *r_timer_lastdraw) { - float zfac = 1.0; - bool use_cam_zoom; - float dist_range[2]; - - use_cam_zoom = (vod->rv3d->persp == RV3D_CAMOB) && !(vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)); - - ED_view3d_dist_range_get(vod->v3d, dist_range); - - if (use_cam_zoom) { - float delta; - delta = (xy[0] - vod->origx + xy[1] - vod->origy) / 10.0f; - vod->rv3d->camzoom = vod->camzoom_prev + (zoom_invert ? -delta : delta); - - CLAMP(vod->rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); - } + float zfac; if (viewzoom == USER_ZOOM_CONT) { double time = PIL_check_seconds_timer(); - float time_step = (float)(time - vod->timer_lastdraw); + float time_step = (float)(time - *r_timer_lastdraw); float fac; if (U.uiflag & USER_ZOOM_HORIZ) { - fac = (float)(vod->origx - xy[0]); + fac = (float)(xy_orig[0] - xy[0]); } else { - fac = (float)(vod->origy - xy[1]); + fac = (float)(xy_orig[1] - xy[1]); } - if (zoom_invert) { + if (zoom_invert != zoom_invert_force) { fac = -fac; } /* oldstyle zoom */ zfac = 1.0f + ((fac / 20.0f) * time_step); - vod->timer_lastdraw = time; + *r_timer_lastdraw = time; } else if (viewzoom == USER_ZOOM_SCALE) { /* method which zooms based on how far you move the mouse */ const int ctr[2] = { - BLI_rcti_cent_x(&vod->ar->winrct), - BLI_rcti_cent_y(&vod->ar->winrct), + BLI_rcti_cent_x(winrct), + BLI_rcti_cent_y(winrct), }; - const float len_new = 5 + len_v2v2_int(ctr, xy); - const float len_old = 5 + len_v2v2_int(ctr, &vod->origx); - zfac = vod->dist_prev * ((len_old + 5) / (len_new + 5)) / vod->rv3d->dist; + float len_new = 5 + len_v2v2_int(ctr, xy); + float len_old = 5 + len_v2v2_int(ctr, xy_orig); + + /* intentionally ignore 'zoom_invert' for scale */ + if (zoom_invert_force) { + SWAP(float, len_new, len_old); + } + + zfac = val_orig * (len_old / max_ff(len_new, 1.0f)) / val; } else { /* USER_ZOOM_DOLLY */ - float len1, len2; + float len_new = 5; + float len_old = 5; if (U.uiflag & USER_ZOOM_HORIZ) { - len1 = (vod->ar->winrct.xmax - xy[0]) + 5; - len2 = (vod->ar->winrct.xmax - vod->origx) + 5; + len_new += (winrct->xmax - xy[0]); + len_old += (winrct->xmax - xy_orig[0]); } else { - len1 = (vod->ar->winrct.ymax - xy[1]) + 5; - len2 = (vod->ar->winrct.ymax - vod->origy) + 5; - } - if (zoom_invert) { - SWAP(float, len1, len2); + len_new += (winrct->ymax - xy[1]); + len_old += (winrct->ymax - xy_orig[1]); } - if (use_cam_zoom) { - /* zfac is ignored in this case, see below */ -#if 0 - zfac = vod->camzoom_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->camzoom; -#endif - } - else { - zfac = vod->dist_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->dist; + if (zoom_invert != zoom_invert_force) { + SWAP(float, len_new, len_old); } + + zfac = val_orig * (2.0f * ((len_new / max_ff(len_old, 1.0f)) - 1.0f) + 1.0f) / val; } - if (!use_cam_zoom) { - if (zfac != 1.0f) { - const float zfac_min = dist_range[0] / vod->rv3d->dist; - const float zfac_max = dist_range[1] / vod->rv3d->dist; - CLAMP(zfac, zfac_min, zfac_max); - if (zfac != 1.0f) { - view_zoom_mouseloc(vod->ar, zfac, vod->oldx, vod->oldy); - } - } + return zfac; +} + +static void viewzoom_apply_camera( + ViewOpsData *vod, const int xy[2], + const short viewzoom, const bool zoom_invert) +{ + float zfac; + float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->camzoom_prev) * 2.0f; + float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f; + + zfac = viewzoom_scale_value( + &vod->ar->winrct, viewzoom, zoom_invert, true, xy, &vod->origx, + zoomfac, zoomfac_prev, + &vod->timer_lastdraw); + + if (zfac != 1.0f && zfac != 0.0f) { + /* calculate inverted, then invert again (needed because of camera zoom scaling) */ + zfac = 1.0f / zfac; + view_zoom_mouseloc_camera( + vod->scene, vod->v3d, + vod->ar, zfac, vod->oldx, vod->oldy); + } + + ED_region_tag_redraw(vod->ar); +} + +static void viewzoom_apply_3d( + ViewOpsData *vod, const int xy[2], + const short viewzoom, const bool zoom_invert) +{ + float zfac; + float dist_range[2]; + + ED_view3d_dist_range_get(vod->v3d, dist_range); + + zfac = viewzoom_scale_value( + &vod->ar->winrct, viewzoom, zoom_invert, false, xy, &vod->origx, + vod->rv3d->dist, vod->dist_prev, + &vod->timer_lastdraw); + + if (zfac != 1.0f) { + const float zfac_min = dist_range[0] / vod->rv3d->dist; + const float zfac_max = dist_range[1] / vod->rv3d->dist; + CLAMP(zfac, zfac_min, zfac_max); + + view_zoom_mouseloc_3d( + vod->ar, zfac, vod->oldx, vod->oldy); } /* these limits were in old code too */ @@ -2234,6 +2308,19 @@ static void viewzoom_apply(ViewOpsData *vod, const int xy[2], const short viewzo ED_region_tag_redraw(vod->ar); } +static void viewzoom_apply( + ViewOpsData *vod, const int xy[2], + const short viewzoom, const bool zoom_invert) +{ + if ((vod->rv3d->persp == RV3D_CAMOB) && + (vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0) + { + viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert); + } + else { + viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert); + } +} static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event) { @@ -2294,6 +2381,7 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event) static int viewzoom_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); View3D *v3d; RegionView3D *rv3d; ScrArea *sa; @@ -2326,22 +2414,26 @@ static int viewzoom_exec(bContext *C, wmOperator *op) ED_view3d_dist_range_get(v3d, dist_range); if (delta < 0) { + const float step = 1.2f; /* this min and max is also in viewmove() */ if (use_cam_zoom) { - rv3d->camzoom -= 10.0f; - if (rv3d->camzoom < RV3D_CAMZOOM_MIN) rv3d->camzoom = RV3D_CAMZOOM_MIN; + view_zoom_mouseloc_camera(scene, v3d, ar, step, mx, my); } - else if (rv3d->dist < dist_range[1]) { - view_zoom_mouseloc(ar, 1.2f, mx, my); + else { + if (rv3d->dist < dist_range[1]) { + view_zoom_mouseloc_3d(ar, step, mx, my); + } } } else { + const float step = 1.0f / 1.2f; if (use_cam_zoom) { - rv3d->camzoom += 10.0f; - if (rv3d->camzoom > RV3D_CAMZOOM_MAX) rv3d->camzoom = RV3D_CAMZOOM_MAX; + view_zoom_mouseloc_camera(scene, v3d, ar, step, mx, my); } - else if (rv3d->dist > dist_range[0]) { - view_zoom_mouseloc(ar, 0.83333f, mx, my); + else { + if (rv3d->dist > dist_range[0]) { + view_zoom_mouseloc_3d(ar, step, mx, my); + } } } @@ -2471,7 +2563,7 @@ void VIEW3D_OT_zoom(wmOperatorType *ot) ot->cancel = viewzoom_cancel; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX); @@ -2725,7 +2817,7 @@ void VIEW3D_OT_dolly(wmOperatorType *ot) ot->cancel = viewdolly_cancel; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX); @@ -2748,29 +2840,15 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar, size = max_fff(afm[0], afm[1], afm[2]); if (ok_dist) { - /* fix up zoom distance if needed */ + char persp; if (rv3d->is_persp) { - float lens, sensor_size; - /* offset the view based on the lens */ if (rv3d->persp == RV3D_CAMOB && ED_view3d_camera_lock_check(v3d, rv3d)) { - CameraParams params; - BKE_camera_params_init(¶ms); - params.clipsta = v3d->near; - params.clipend = v3d->far; - BKE_camera_params_from_object(¶ms, v3d->camera); - - lens = params.lens; - sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y); + persp = RV3D_CAMOB; } else { - lens = v3d->lens; - sensor_size = DEFAULT_SENSOR_WIDTH; + persp = RV3D_PERSP; } - size = ED_view3d_radius_to_persp_dist(focallength_to_fov(lens, sensor_size), size / 2.0f) * VIEW3D_MARGIN; - - /* do not zoom closer than the near clipping plane */ - size = max_ff(size, v3d->near * 1.5f); } else { /* ortho */ if (size < 0.0001f) { @@ -2779,7 +2857,15 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar, } else { /* adjust zoom so it looks nicer */ - size = ED_view3d_radius_to_ortho_dist(v3d->lens, size / 2.0f) * VIEW3D_MARGIN; + persp = RV3D_ORTHO; + } + } + + if (ok_dist) { + new_dist = ED_view3d_radius_to_dist(v3d, ar, persp, true, (size / 2) * VIEW3D_MARGIN); + if (rv3d->is_persp) { + /* don't zoom closer than the near clipping plane */ + new_dist = max_ff(new_dist, v3d->near * 1.5f); } } } @@ -2787,15 +2873,6 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar, mid_v3_v3v3(new_ofs, min, max); negate_v3(new_ofs); - new_dist = size; - - /* correction for window aspect ratio */ - if (ar->winy > 2 && ar->winx > 2) { - size = (float)ar->winx / (float)ar->winy; - if (size < 1.0f) size = 1.0f / size; - new_dist *= size; - } - if (rv3d->persp == RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)) { rv3d->persp = RV3D_PERSP; ED_view3d_smooth_view(C, v3d, ar, v3d->camera, NULL, @@ -3703,22 +3780,6 @@ static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar, } if (align_active == false) { - /* normal operation */ - if (rv3d->viewlock & RV3D_LOCKED) { - /* only pass on if */ - - /* nice confusing if-block */ - if (!((rv3d->view == RV3D_VIEW_FRONT && view == RV3D_VIEW_BACK) || - (rv3d->view == RV3D_VIEW_BACK && view == RV3D_VIEW_FRONT) || - (rv3d->view == RV3D_VIEW_RIGHT && view == RV3D_VIEW_LEFT) || - (rv3d->view == RV3D_VIEW_LEFT && view == RV3D_VIEW_RIGHT) || - (rv3d->view == RV3D_VIEW_BOTTOM && view == RV3D_VIEW_TOP) || - (rv3d->view == RV3D_VIEW_TOP && view == RV3D_VIEW_BOTTOM))) - { - return; - } - } - rv3d->view = view; } @@ -3765,10 +3826,6 @@ static int viewnumpad_exec(bContext *C, wmOperator *op) viewnum = RNA_enum_get(op->ptr, "type"); align_active = RNA_boolean_get(op->ptr, "align_active"); - /* set this to zero, gets handled in axis_set_view */ - if (rv3d->viewlock & RV3D_LOCKED) - align_active = false; - /* Use this to test if we started out with a camera */ if (rv3d->persp == RV3D_CAMOB) { @@ -3894,23 +3951,37 @@ static int vieworbit_exec(bContext *C, wmOperator *op) ARegion *ar; RegionView3D *rv3d; int orbitdir; + char view_opposite; + PropertyRNA *prop_angle = RNA_struct_find_property(op->ptr, "angle"); + float angle = RNA_property_is_set(op->ptr, prop_angle) ? + RNA_property_float_get(op->ptr, prop_angle) : DEG2RADF((float)U.pad_rot_angle); /* no NULL check is needed, poll checks */ - ED_view3d_context_user_region(C, &v3d, &ar); + v3d = CTX_wm_view3d(C); + ar = CTX_wm_region(C); rv3d = ar->regiondata; + /* support for switching to the opposite view (even when in locked views) */ + view_opposite = (fabsf(angle) == (float)M_PI) ? ED_view3d_axis_view_opposite(rv3d->view) : RV3D_VIEW_USER; orbitdir = RNA_enum_get(op->ptr, "type"); - if ((rv3d->viewlock & RV3D_LOCKED) == 0) { + if ((rv3d->viewlock & RV3D_LOCKED) && (view_opposite == RV3D_VIEW_USER)) { + /* no NULL check is needed, poll checks */ + ED_view3d_context_user_region(C, &v3d, &ar); + rv3d = ar->regiondata; + } + + if ((rv3d->viewlock & RV3D_LOCKED) == 0 || (view_opposite != RV3D_VIEW_USER)) { if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) { int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - float angle = DEG2RADF((float)U.pad_rot_angle); float quat_mul[4]; float quat_new[4]; float ofs_new[3]; float *ofs_new_pt = NULL; - view3d_ensure_persp(v3d, ar); + if (view_opposite == RV3D_VIEW_USER) { + view3d_ensure_persp(v3d, ar); + } if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) { const float zvec[3] = {0.0f, 0.0f, 1.0f}; @@ -3933,7 +4004,15 @@ static int vieworbit_exec(bContext *C, wmOperator *op) } mul_qt_qtqt(quat_new, rv3d->viewquat, quat_mul); - rv3d->view = RV3D_VIEW_USER; + + if (view_opposite != RV3D_VIEW_USER) { + rv3d->view = view_opposite; + /* avoid float in-precision, just get a new orientation */ + ED_view3d_quat_from_axis_view(view_opposite, quat_new); + } + else { + rv3d->view = RV3D_VIEW_USER; + } if (U.uiflag & USER_ORBIT_SELECTION) { float dyn_ofs[3]; @@ -3964,6 +4043,8 @@ static int vieworbit_exec(bContext *C, wmOperator *op) void VIEW3D_OT_view_orbit(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "View Orbit"; ot->description = "Orbit the view"; @@ -3977,7 +4058,11 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot) ot->flag = 0; /* properties */ + prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + ot->prop = RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit"); + } @@ -4429,20 +4514,6 @@ void VIEW3D_OT_background_image_remove(wmOperatorType *ot) /* ********************* set clipping operator ****************** */ -static void calc_clipping_plane(float clip[6][4], const BoundBox *clipbb, const bool is_flip) -{ - int val; - - for (val = 0; val < 4; val++) { - normal_tri_v3(clip[val], clipbb->vec[val], clipbb->vec[val == 3 ? 0 : val + 1], clipbb->vec[val + 4]); - if (UNLIKELY(is_flip)) { - negate_v3(clip[val]); - } - - clip[val][3] = -dot_v3v3(clip[val], clipbb->vec[val]); - } -} - static void calc_local_clipping(float clip_local[6][4], BoundBox *clipbb, float mat[4][4]) { BoundBox clipbb_local; @@ -4455,7 +4526,7 @@ static void calc_local_clipping(float clip_local[6][4], BoundBox *clipbb, float mul_v3_m4v3(clipbb_local.vec[i], imat, clipbb->vec[i]); } - calc_clipping_plane(clip_local, &clipbb_local, is_negative_m4(mat)); + ED_view3d_clipping_calc_from_boundbox(clip_local, &clipbb_local, is_negative_m4(mat)); } void ED_view3d_clipping_local(RegionView3D *rv3d, float mat[4][4]) @@ -4536,7 +4607,7 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2]) Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); + RegionView3D *rv3d = ar->regiondata; bool flip; bool depth_used = false; @@ -4571,9 +4642,28 @@ void ED_view3d_cursor3d_update(bContext *C, const int mval[2]) { Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); - float *fp = ED_view3d_cursor3d_get(scene, v3d); - ED_view3d_cursor3d_position(C, fp, mval); + float *fp_curr = ED_view3d_cursor3d_get(scene, v3d); + float fp_prev[3]; + + copy_v3_v3(fp_prev, fp_curr); + + ED_view3d_cursor3d_position(C, fp_curr, mval); + + /* offset the cursor lock to avoid jumping to new offset */ + if (v3d->ob_centre_cursor) { + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + + float co_curr[2], co_prev[2]; + + if ((ED_view3d_project_float_global(ar, fp_prev, co_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) && + (ED_view3d_project_float_global(ar, fp_curr, co_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) + { + rv3d->ofs_lock[0] += (co_curr[0] - co_prev[0]) / (ar->winx * 0.5f); + rv3d->ofs_lock[1] += (co_curr[1] - co_prev[1]) / (ar->winy * 0.5f); + } + } if (v3d && v3d->localvd) WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); @@ -4599,7 +4689,7 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot) /* api callbacks */ ot->invoke = view3d_cursor3d_invoke; - ot->poll = ED_operator_view3d_active; + ot->poll = ED_operator_region_view3d_active; /* flags */ // ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; @@ -4725,16 +4815,24 @@ bool ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d, bglMats mats; /* ZBuffer depth vars */ float depth_close; double cent[2], p[3]; + int margin_arr[] = {0, 2, 4}; + int i; + bool depth_ok = false; /* Get Z Depths, needed for perspective, nice for ortho */ bgl_get_mats(&mats); ED_view3d_draw_depth(scene, ar, v3d, alphaoverride); - depth_close = view_autodist_depth_margin(ar, mval, 4); + /* Attempt with low margin's first */ + i = 0; + do { + depth_close = view_autodist_depth_margin(ar, mval, margin_arr[i++] * U.pixelsize); + depth_ok = (depth_close != FLT_MAX); + } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr))); - if (depth_close != FLT_MAX) { - cent[0] = (double)mval[0]; - cent[1] = (double)mval[1]; + if (depth_ok) { + cent[0] = (double)mval[0] + 0.5; + cent[1] = (double)mval[1] + 0.5; if (gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) @@ -4785,8 +4883,8 @@ bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_world if (depth == FLT_MAX) return false; - cent[0] = (double)mval[0]; - cent[1] = (double)mval[1]; + cent[0] = (double)mval[0] + 0.5; + cent[1] = (double)mval[1] + 0.5; bgl_get_mats(&mats); diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index da77c4f75f7..469a7e63903 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -296,10 +296,10 @@ static void fly_update_header(bContext *C, FlyInfo *fly) "Ctrl: free look, " "X: Upright x axis (%s), " "Z: Upright z axis (%s), " - "(+/- | Wheel): speed"), + "(+/- | Wheel): speed"), WM_bool_as_string(fly->xlock != FLY_AXISLOCK_STATE_OFF), - WM_bool_as_string(fly->zlock != FLY_AXISLOCK_STATE_OFF)); + WM_bool_as_string(fly->zlock != FLY_AXISLOCK_STATE_OFF)); ED_area_headerprint(CTX_wm_area(C), header); #undef HEADER_LENGTH @@ -806,7 +806,7 @@ static int flyApply(bContext *C, FlyInfo *fly) copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); mul_m3_v3(mat, upvec); /* Rotate about the relative up vec */ - axis_angle_to_quat(tmp_quat, upvec, (float)moffset[1] * time_redraw * -FLY_ROTATE_FAC); + axis_angle_to_quat(tmp_quat, upvec, moffset[1] * time_redraw * -FLY_ROTATE_FAC); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); if (fly->xlock != FLY_AXISLOCK_STATE_OFF) @@ -836,7 +836,7 @@ static int flyApply(bContext *C, FlyInfo *fly) } /* Rotate about the relative up vec */ - axis_angle_to_quat(tmp_quat, upvec, (float)moffset[0] * time_redraw * FLY_ROTATE_FAC); + axis_angle_to_quat(tmp_quat, upvec, moffset[0] * time_redraw * FLY_ROTATE_FAC); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); if (fly->xlock != FLY_AXISLOCK_STATE_OFF) diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 11ed9867e2f..95532bc09a5 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -105,8 +105,8 @@ static void view3d_layers_editmode_ensure(Scene *scene, View3D *v3d) if (scene->obedit && (scene->obedit->lay & v3d->lay) == 0) { int bit; for (bit = 0; bit < 32; bit++) { - if (scene->obedit->lay & (1 << bit)) { - v3d->lay |= 1 << bit; + if (scene->obedit->lay & (1u << bit)) { + v3d->lay |= (1u << bit); break; } } @@ -161,8 +161,8 @@ static int view3d_layers_exec(bContext *C, wmOperator *op) v3d->layact = 1 << nr; else if ((v3d->lay & v3d->layact) == 0) { for (bit = 0; bit < 32; bit++) { - if (v3d->lay & (1 << bit)) { - v3d->layact = 1 << bit; + if (v3d->lay & (1u << bit)) { + v3d->layact = (1u << bit); break; } } @@ -340,7 +340,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) } /* Manipulators aren't used in paint modes */ - if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT)) { + if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT, OB_MODE_HAIR_EDIT)) { /* masks aren't used for sculpt and particle painting */ PointerRNA meshptr; diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index a9b6d96d5d1..f4ecde79365 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -41,14 +41,14 @@ struct BoundBox; struct DerivedMesh; struct Object; struct SmokeDomainSettings; -struct ViewContext; struct bAnimVizSettings; struct bContext; struct bMotionPath; struct bPoseChannel; -struct bScreen; struct Mesh; -struct SimDebugData; +struct BMEditStrands; +struct Strands; +struct StrandsChildren; struct wmNDOFMotionData; struct wmOperatorType; struct wmWindowManager; @@ -184,6 +184,10 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d, /* drawsimdebug.c */ void draw_sim_debug_data(Scene *scene, View3D *v3d, ARegion *ar); +/* drawstrands.c */ +void draw_strands(Scene *scene, View3D *v3d, ARegion *ar, struct Object *ob, struct Strands *strands, struct StrandsChildren *children, short dflag); +void draw_strands_edit_hair(Scene *scene, View3D *v3d, ARegion *ar, struct BMEditStrands *edit); + /* view3d_draw.c */ void view3d_main_area_draw(const struct bContext *C, struct ARegion *ar); void ED_view3d_draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, bool alphaoverride); @@ -210,7 +214,7 @@ void VIEW3D_OT_localview(struct wmOperatorType *ot); void VIEW3D_OT_game_start(struct wmOperatorType *ot); -bool ED_view3d_boundbox_clip_ex(RegionView3D *rv3d, const struct BoundBox *bb, float obmat[4][4]); +bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const struct BoundBox *bb, float obmat[4][4]); bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const struct BoundBox *bb); void ED_view3d_smooth_view_ex( @@ -227,8 +231,8 @@ void ED_view3d_smooth_view( const float *ofs, const float *quat, const float *dist, const float *lens, const int smooth_viewtx); -void view3d_winmatrix_set(ARegion *ar, View3D *v3d, const rctf *rect); -void view3d_viewmatrix_set(Scene *scene, View3D *v3d, RegionView3D *rv3d); +void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rctf *rect); +void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d); void fly_modal_keymap(struct wmKeyConfig *keyconf); void walk_modal_keymap(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 64124a136e8..56faf945fb9 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -236,8 +236,9 @@ void view3d_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "VIEW3D_OT_navigate", FKEY, KM_PRESS, KM_SHIFT, 0); + /* value is set to KM_NOTHING to avoid conflicts with click type (see T44251) */ WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0); - + WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEPAN, 0, 0, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEROTATE, 0, 0, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_move", MOUSEPAN, 0, KM_SHIFT, 0); @@ -299,6 +300,9 @@ void view3d_keymap(wmKeyConfig *keyconf) RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD8, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANUP); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", PAD4, KM_PRESS, KM_SHIFT, 0)->ptr, "type", V3D_VIEW_STEPLEFT); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", PAD6, KM_PRESS, KM_SHIFT, 0)->ptr, "type", V3D_VIEW_STEPRIGHT); + kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", PAD9, KM_PRESS, 0, 0); + RNA_enum_set(kmi->ptr, "type", V3D_VIEW_STEPRIGHT); + RNA_float_set(kmi->ptr, "angle", (float)M_PI); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANRIGHT); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANLEFT); @@ -523,3 +527,4 @@ void view3d_keymap(wmKeyConfig *keyconf) viewzoom_modal_keymap(keyconf); viewdolly_modal_keymap(keyconf); } + diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 74e3fde0eec..ba0626c58ea 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -605,6 +605,14 @@ void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, Object *ob, float pm mul_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat); } +void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, float obmat[4][4], float pmat[4][4]) +{ + float vmat[4][4]; + + mul_m4_m4m4(vmat, (float (*)[4])rv3d->viewmat, obmat); + mul_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat); +} + /** * Uses window coordinates (x,y) and depth component z to find a point in * modelspace */ diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index eba31866f54..98b1e846c70 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -187,8 +187,9 @@ typedef struct RulerInfo { /* wm state */ wmWindow *win; - ARegion *ar; + ScrArea *sa; void *draw_handle_pixel; + ARegion *ar; /* re-assigned every modal update */ } RulerInfo; /* -------------------------------------------------------------------- */ @@ -435,7 +436,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a UnitSettings *unit = &scene->unit; RulerItem *ruler_item; RulerInfo *ruler_info = arg; - RegionView3D *rv3d = ruler_info->ar->regiondata; + RegionView3D *rv3d = ar->regiondata; // ARegion *ar = ruler_info->ar; const float cap_size = 4.0f; const float bg_margin = 4.0f * U.pixelsize; @@ -798,12 +799,14 @@ static int view3d_ruler_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE op->customdata = ruler_info; ruler_info->win = win; - ruler_info->ar = ar; + ruler_info->sa = sa; ruler_info->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ruler_info_draw_pixel, ruler_info, REGION_DRAW_POST_PIXEL); view3d_ruler_header_update(sa); + op->flag |= OP_IS_MODAL_CURSOR_REGION; + WM_cursor_modal_set(win, BC_CROSSCURSOR); WM_event_add_modal_handler(C, op); @@ -825,15 +828,17 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event) int exit_code = OPERATOR_RUNNING_MODAL; RulerInfo *ruler_info = op->customdata; ScrArea *sa = CTX_wm_area(C); - ARegion *ar = ruler_info->ar; + ARegion *ar = CTX_wm_region(C); RegionView3D *rv3d = ar->regiondata; /* its possible to change spaces while running the operator [#34894] */ - if (UNLIKELY(ar != CTX_wm_region(C))) { + if (UNLIKELY(sa != ruler_info->sa)) { exit_code = OPERATOR_FINISHED; goto exit; } + ruler_info->ar = ar; + switch (event->type) { case LEFTMOUSE: if (event->val == KM_RELEASE) { @@ -1019,6 +1024,13 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event) } + if (ruler_info->state == RULER_STATE_DRAG) { + op->flag &= ~OP_IS_MODAL_CURSOR_REGION; + } + else { + op->flag |= OP_IS_MODAL_CURSOR_REGION; + } + if (do_draw) { view3d_ruler_header_update(sa); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index d0f22ba58c5..1847de3c6a2 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -85,9 +85,11 @@ #include "ED_armature.h" #include "ED_curve.h" +#include "ED_physics.h" #include "ED_particle.h" #include "ED_mesh.h" #include "ED_object.h" +#include "ED_physics.h" #include "ED_screen.h" #include "ED_sculpt.h" #include "ED_mball.h" @@ -725,7 +727,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, } static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) { - const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT); + const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Object *ob = vc->obact; Mesh *me = ob->data; rcti rect; @@ -834,6 +836,8 @@ static void view3d_lasso_select(bContext *C, ViewContext *vc, } else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) PE_lasso_select(C, mcords, moves, extend, select); + else if (ob && (ob->mode & OB_MODE_HAIR_EDIT)) + ED_hair_lasso_select(C, mcords, moves, extend, select); else { do_lasso_select_objects(vc, mcords, moves, extend, select); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene); @@ -1641,7 +1645,7 @@ static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, con } static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) { - const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT); + const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Mesh *me; MVert *mvert; struct ImBuf *ibuf; @@ -1662,7 +1666,7 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo if (use_zbuf) { selar = MEM_callocN(me->totvert + 1, "selar"); - view3d_validate_backbuf(vc); + ED_view3d_backbuf_validate(vc); ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect); rt = ibuf->rect; @@ -2146,6 +2150,9 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) { ret = PE_border_select(C, &rect, select, extend); } + else if (vc.obact && vc.obact->mode & OB_MODE_HAIR_EDIT) { + ret = ED_hair_border_select(C, &rect, select, extend); + } else { /* object mode with none active */ ret = do_object_pose_box_select(C, &vc, &rect, select, extend); } @@ -2185,7 +2192,7 @@ void VIEW3D_OT_select_border(wmOperatorType *ot) static bool mouse_weight_paint_vertex_select(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, Object *obact) { View3D *v3d = CTX_wm_view3d(C); - const int use_zbuf = (v3d->flag & V3D_ZBUF_SELECT); + const bool use_zbuf = (v3d->flag & V3D_ZBUF_SELECT) != 0; Mesh *me = obact->data; /* already checked for NULL */ unsigned int index = 0; @@ -2276,6 +2283,8 @@ static int view3d_select_exec(bContext *C, wmOperator *op) } else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) return PE_mouse_particles(C, location, extend, deselect, toggle); + else if (obact && obact->mode & OB_MODE_HAIR_EDIT) + return ED_hair_mouse_select(C, location, extend, deselect, toggle); else if (obact && BKE_paint_select_face_test(obact)) retval = paintface_mouse_select(C, obact, location, extend, deselect, toggle); else if (BKE_paint_select_vert_test(obact)) @@ -2453,7 +2462,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, } static void paint_vertsel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) { - const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT); + const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Object *ob = vc->obact; Mesh *me = ob->data; bool bbsel; @@ -2791,7 +2800,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) RNA_int_get(op->ptr, "y")}; if (CTX_data_edit_object(C) || BKE_paint_select_elem_test(obact) || - (obact && (obact->mode & (OB_MODE_PARTICLE_EDIT | OB_MODE_POSE))) ) + (obact && (obact->mode & (OB_MODE_PARTICLE_EDIT | OB_MODE_POSE | OB_MODE_HAIR_EDIT))) ) { ViewContext vc; @@ -2811,10 +2820,16 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) paint_vertsel_circle_select(&vc, select, mval, (float)radius); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); } - else if (obact->mode & OB_MODE_POSE) + else if (obact->mode & OB_MODE_POSE) { pose_circle_select(&vc, select, mval, (float)radius); - else + } + else if (obact->mode & OB_MODE_HAIR_EDIT) { + ED_hair_circle_select(C, select, mval, (float)radius); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); + } + else { return PE_circle_select(C, select, mval, (float)radius); + } } else if (obact && obact->mode & OB_MODE_SCULPT) { return OPERATOR_CANCELLED; diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 0608c35129d..8bb84d00c83 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -31,9 +31,7 @@ #include "DNA_armature_types.h" -#include "DNA_curve_types.h" #include "DNA_object_types.h" -#include "DNA_meta_types.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" @@ -43,11 +41,9 @@ #include "BKE_armature.h" #include "BKE_context.h" #include "BKE_depsgraph.h" -#include "BKE_lattice.h" #include "BKE_main.h" #include "BKE_mball.h" #include "BKE_object.h" -#include "BKE_editmesh.h" #include "BKE_tracking.h" #include "WM_api.h" @@ -60,7 +56,6 @@ #include "ED_transverts.h" #include "ED_keyframing.h" #include "ED_screen.h" -#include "ED_curve.h" #include "view3d_intern.h" diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 5a3893f733f..e9cb6dcdc44 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -44,6 +44,7 @@ #include "BKE_camera.h" #include "BKE_context.h" #include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" #include "BKE_object.h" #include "BKE_global.h" #include "BKE_main.h" @@ -609,6 +610,20 @@ void VIEW3D_OT_object_as_camera(wmOperatorType *ot) /* ********************************** */ +void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip) +{ + int val; + + for (val = 0; val < 4; val++) { + normal_tri_v3(clip[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]); + if (UNLIKELY(is_flip)) { + negate_v3(clip[val]); + } + + clip[val][3] = -dot_v3v3(clip[val], bb->vec[val]); + } +} + void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], bglMats *mats, const rcti *rect) { float modelview[4][4]; @@ -644,16 +659,7 @@ void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], bglMats *mats, co ((float *)modelview)[a] = mats->modelview[a]; flip_sign = is_negative_m4(modelview); - /* then plane equations */ - for (val = 0; val < 4; val++) { - - normal_tri_v3(planes[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]); - - if (flip_sign) - negate_v3(planes[val]); - - planes[val][3] = -dot_v3v3(planes[val], bb->vec[val]); - } + ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign); } static bool view3d_boundbox_clip_m4(const BoundBox *bb, float persmatob[4][4]) @@ -683,7 +689,7 @@ static bool view3d_boundbox_clip_m4(const BoundBox *bb, float persmatob[4][4]) return false; } -bool ED_view3d_boundbox_clip_ex(RegionView3D *rv3d, const BoundBox *bb, float obmat[4][4]) +bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const BoundBox *bb, float obmat[4][4]) { /* return 1: draw */ @@ -692,7 +698,7 @@ bool ED_view3d_boundbox_clip_ex(RegionView3D *rv3d, const BoundBox *bb, float ob if (bb == NULL) return true; if (bb->flag & BOUNDBOX_DISABLED) return true; - mul_m4_m4m4(persmatob, rv3d->persmat, obmat); + mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat); return view3d_boundbox_clip_m4(bb, persmatob); } @@ -705,7 +711,7 @@ bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb) return view3d_boundbox_clip_m4(bb, rv3d->persmatob); } -float ED_view3d_depth_read_cached(ViewContext *vc, int x, int y) +float ED_view3d_depth_read_cached(const ViewContext *vc, int x, int y) { ViewDepths *vd = vc->rv3d->depths; @@ -724,16 +730,19 @@ void ED_view3d_depth_tag_update(RegionView3D *rv3d) rv3d->depths->damaged = true; } -void ED_view3d_dist_range_get(struct View3D *v3d, - float r_dist_range[2]) +void ED_view3d_dist_range_get( + const View3D *v3d, + float r_dist_range[2]) { r_dist_range[0] = v3d->grid * 0.001f; r_dist_range[1] = v3d->far * 10.0f; } /* copies logic of get_view3d_viewplane(), keep in sync */ -bool ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *r_clipsta, float *r_clipend, - const bool use_ortho_factor) +bool ED_view3d_clip_range_get( + const View3D *v3d, const RegionView3D *rv3d, + float *r_clipsta, float *r_clipend, + const bool use_ortho_factor) { CameraParams params; @@ -753,8 +762,9 @@ bool ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *r_clipsta, } /* also exposed in previewrender.c */ -bool ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy, - rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize) +bool ED_view3d_viewplane_get( + const View3D *v3d, const RegionView3D *rv3d, int winx, int winy, + rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize) { CameraParams params; @@ -792,7 +802,7 @@ void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist) /** * \param rect optional for picking (can be NULL). */ -void view3d_winmatrix_set(ARegion *ar, View3D *v3d, const rctf *rect) +void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rctf *rect) { RegionView3D *rv3d = ar->regiondata; rctf viewplane; @@ -891,13 +901,28 @@ char ED_view3d_lock_view_from_index(int index) } +char ED_view3d_axis_view_opposite(char view) +{ + switch (view) { + case RV3D_VIEW_FRONT: return RV3D_VIEW_BACK; + case RV3D_VIEW_BACK: return RV3D_VIEW_FRONT; + case RV3D_VIEW_LEFT: return RV3D_VIEW_RIGHT; + case RV3D_VIEW_RIGHT: return RV3D_VIEW_LEFT; + case RV3D_VIEW_TOP: return RV3D_VIEW_BOTTOM; + case RV3D_VIEW_BOTTOM: return RV3D_VIEW_TOP; + } + + return RV3D_VIEW_USER; +} + + bool ED_view3d_lock(RegionView3D *rv3d) { return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->viewquat); } /* don't set windows active in here, is used by renderwin too */ -void view3d_viewmatrix_set(Scene *scene, View3D *v3d, RegionView3D *rv3d) +void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d) { if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */ if (v3d->camera) { @@ -936,7 +961,7 @@ void view3d_viewmatrix_set(Scene *scene, View3D *v3d, RegionView3D *rv3d) } else if (v3d->ob_centre_cursor) { float vec[3]; - copy_v3_v3(vec, ED_view3d_cursor3d_get(scene, v3d)); + copy_v3_v3(vec, ED_view3d_cursor3d_get(scene, (View3D *)v3d)); translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]); use_lock_ofs = true; } @@ -1006,23 +1031,55 @@ static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegi lb = object_duplilist(G.main->eval_ctx, scene, base->object); for (dob = lb->first; dob; dob = dob->next) { - float omat[4][4]; + /* for restoring after override */ + DupliObjectData *dob_data = NULL; + DerivedMesh *store_final_dm; + float store_obmat[4][4]; tbase.object = dob->ob; - copy_m4_m4(omat, dob->ob->obmat); + copy_m4_m4(store_obmat, dob->ob->obmat); copy_m4_m4(dob->ob->obmat, dob->mat); + store_final_dm = dob->ob->derivedFinal; /* extra service: draw the duplicator in drawtype of parent */ /* MIN2 for the drawtype to allow bounding box objects in groups for lods */ dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx; + /* override final DM */ + tbase.object->transflag &= ~OB_IS_DUPLI_CACHE; + if (base->object->dup_cache) { + dob_data = BKE_dupli_cache_find_data(base->object->dup_cache, tbase.object); + if (dob_data && dob_data->dm) { + tbase.object->transflag |= OB_IS_DUPLI_CACHE; + + tbase.object->derivedFinal = dob_data->dm; + } + } + draw_object(scene, ar, v3d, &tbase, DRAW_PICKING | DRAW_CONSTCOLOR); + /* restore final DM */ + if (tbase.object->transflag & OB_IS_DUPLI_CACHE) { + DerivedMesh *cur = tbase.object->derivedFinal; + + /* in some cases drawing code can recreate the derivedFinal, + * make sure we free those first before restoring + */ + if (cur && cur != dob_data->dm) { + cur->needsFree = 1; + cur->release(cur); + } + + tbase.object->transflag &= ~OB_IS_DUPLI_CACHE; + tbase.object->derivedFinal = store_final_dm; + } + tbase.object->dt = dt; tbase.object->dtx = dtx; - copy_m4_m4(dob->ob->obmat, omat); + /* restore obmat and final DM */ + copy_m4_m4(dob->ob->obmat, store_obmat); } free_object_duplilist(lb); } @@ -1194,7 +1251,7 @@ static bool view3d_localview_init( View3D *v3d = sa->spacedata.first; Base *base; float min[3], max[3], box[3], mid[3]; - float size = 0.0f, size_persp = 0.0f, size_ortho = 0.0f; + float size = 0.0f; unsigned int locallay; bool ok = false; @@ -1232,13 +1289,6 @@ static bool view3d_localview_init( sub_v3_v3v3(box, max, min); size = max_fff(box[0], box[1], box[2]); - - /* do not zoom closer than the near clipping plane */ - size = max_ff(size, v3d->near * 1.5f); - - /* perspective size (we always switch out of camera view so no need to use its lens size) */ - size_persp = ED_view3d_radius_to_persp_dist(focallength_to_fov(v3d->lens, DEFAULT_SENSOR_WIDTH), size / 2.0f) * VIEW3D_MARGIN; - size_ortho = ED_view3d_radius_to_ortho_dist(v3d->lens, size / 2.0f) * VIEW3D_MARGIN; } if (ok == true) { @@ -1255,6 +1305,7 @@ static bool view3d_localview_init( for (ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->regiontype == RGN_TYPE_WINDOW) { RegionView3D *rv3d = ar->regiondata; + bool ok_dist = true; /* new view values */ Object *camera_old = NULL; @@ -1270,25 +1321,24 @@ static bool view3d_localview_init( camera_old = v3d->camera; } - /* perspective should be a bit farther away to look nice */ - if (rv3d->persp != RV3D_ORTHO) { - dist_new = size_persp; - } - else { - dist_new = size_ortho; + if (rv3d->persp == RV3D_ORTHO) { + if (size < 0.0001f) { + ok_dist = false; + } } - /* correction for window aspect ratio */ - if (ar->winy > 2 && ar->winx > 2) { - float asp = (float)ar->winx / (float)ar->winy; - if (asp < 1.0f) asp = 1.0f / asp; - dist_new *= asp; + if (ok_dist) { + dist_new = ED_view3d_radius_to_dist(v3d, ar, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN); + if (rv3d->persp == RV3D_PERSP) { + /* don't zoom closer than the near clipping plane */ + dist_new = max_ff(dist_new, v3d->near * 1.5f); + } } ED_view3d_smooth_view_ex( wm, win, sa, v3d, ar, camera_old, NULL, - ofs_new, NULL, &dist_new, NULL, + ofs_new, NULL, ok_dist ? &dist_new : NULL, NULL, smooth_viewtx); } } @@ -1695,21 +1745,116 @@ void VIEW3D_OT_game_start(wmOperatorType *ot) /* ************************************** */ -float ED_view3d_pixel_size(RegionView3D *rv3d, const float co[3]) +float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3]) { - return mul_project_m4_v3_zfac(rv3d->persmat, co) * rv3d->pixsize * U.pixelsize; + return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize * U.pixelsize; } -float ED_view3d_radius_to_persp_dist(const float angle, const float radius) +float ED_view3d_radius_to_dist_persp(const float angle, const float radius) { - return (radius / 2.0f) * fabsf(1.0f / cosf((((float)M_PI) - angle) / 2.0f)); + return radius * (1.0f / tanf(angle / 2.0f)); } -float ED_view3d_radius_to_ortho_dist(const float lens, const float radius) +float ED_view3d_radius_to_dist_ortho(const float lens, const float radius) { return radius / (DEFAULT_SENSOR_WIDTH / lens); } +/** + * Return a new RegionView3D.dist value to fit the \a radius. + * + * \note Depth isn't taken into account, this will fit a flat plane exactly, + * but points towards the view (with a perspective projection), + * may be within the radius but outside the view. eg: + * + * <pre> + * + + * pt --> + /^ radius + * / | + * / | + * view + + + * \ | + * \ | + * \| + * + + * </pre> + * + * \param ar Can be NULL if \a use_aspect is false. + * \param persp Allow the caller to tell what kind of perspective to use (ortho/view/camera) + * \param use_aspect Increase the distance to account for non 1:1 view aspect. + * \param radius The radius will be fitted exactly, typically pre-scaled by a margin (#VIEW3D_MARGIN). + */ +float ED_view3d_radius_to_dist( + const View3D *v3d, const ARegion *ar, + const char persp, const bool use_aspect, + const float radius) +{ + float dist; + + BLI_assert(ELEM(persp, RV3D_ORTHO, RV3D_PERSP, RV3D_CAMOB)); + BLI_assert((persp != RV3D_CAMOB) || v3d->camera); + + if (persp == RV3D_ORTHO) { + dist = ED_view3d_radius_to_dist_ortho(v3d->lens, radius); + } + else { + float lens, sensor_size, zoom; + float angle; + + if (persp == RV3D_CAMOB) { + CameraParams params; + BKE_camera_params_init(¶ms); + params.clipsta = v3d->near; + params.clipend = v3d->far; + BKE_camera_params_from_object(¶ms, v3d->camera); + + lens = params.lens; + sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y); + + /* ignore 'rv3d->camzoom' because we wan't to fit to the cameras frame */ + zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB; + } + else { + lens = v3d->lens; + sensor_size = DEFAULT_SENSOR_WIDTH; + zoom = CAMERA_PARAM_ZOOM_INIT_PERSP; + } + + angle = focallength_to_fov(lens, sensor_size); + + /* zoom influences lens, correct this by scaling the angle as a distance (by the zoom-level) */ + angle = atanf(tanf(angle / 2.0f) * zoom) * 2.0f; + + dist = ED_view3d_radius_to_dist_persp(angle, radius); + } + + if (use_aspect) { + const RegionView3D *rv3d = ar->regiondata; + + float winx, winy; + + if (persp == RV3D_CAMOB) { + /* camera frame x/y in pixels */ + winx = ar->winx / rv3d->viewcamtexcofac[0]; + winy = ar->winy / rv3d->viewcamtexcofac[1]; + } + else { + winx = ar->winx; + winy = ar->winy; + } + + if (winx && winy) { + float aspect = winx / winy; + if (aspect < 1.0f) { + aspect = 1.0f / aspect; + } + dist *= aspect; + } + } + + return dist; +} + /* view matrix properties utilities */ /* unused */ diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 191eeb05c71..1d5c2a3a169 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -26,8 +26,6 @@ /* defines VIEW3D_OT_navigate - walk modal operator */ -//#define NDOF_WALK_DEBUG -//#define NDOF_WALK_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */ #include "DNA_scene_types.h" #include "DNA_object_types.h" @@ -58,6 +56,11 @@ #include "view3d_intern.h" /* own include */ +//#define NDOF_WALK_DEBUG +//#define NDOF_WALK_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */ + +#define USE_TABLET_SUPPORT + /* prototypes */ static float getVelocityZeroTime(const float gravity, const float velocity); @@ -220,8 +223,7 @@ void walk_modal_keymap(wmKeyConfig *keyconf) } -typedef struct WalkTeleport -{ +typedef struct WalkTeleport { eWalkTeleportState state; float duration; /* from user preferences */ float origin[3]; @@ -277,6 +279,14 @@ typedef struct WalkInfo { /* mouse reverse */ bool is_reversed; +#ifdef USE_TABLET_SUPPORT + /* check if we had a cursor event before */ + bool is_cursor_first; + + /* tablet devices (we can't relocate the cursor) */ + bool is_cursor_absolute; +#endif + /* gravity system */ eWalkGravityState gravity_state; float gravity; @@ -345,7 +355,7 @@ static void walk_update_header(bContext *C, WalkInfo *walk) char header[HEADER_LENGTH]; BLI_snprintf(header, HEADER_LENGTH, IFACE_("LMB/Return: confirm, Esc/RMB: cancel, " - "Tab: gravity (%s), " + "Tab: gravity (%s), " "WASD: move around, " "Shift: fast, Alt: slow, " "QE: up and down, MMB/Space: teleport, V: jump, " @@ -520,6 +530,12 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0); +#ifdef USE_TABLET_SUPPORT + walk->is_cursor_first = true; + + walk->is_cursor_absolute = false; +#endif + walk->active_directions = 0; #ifdef NDOF_WALK_DRAW_TOOMUCH @@ -587,10 +603,16 @@ static int walkEnd(bContext *C, WalkInfo *walk) /* restore the cursor */ WM_cursor_modal_restore(win); - /* center the mouse */ - WM_cursor_warp(win, - walk->ar->winrct.xmin + walk->center_mval[0], - walk->ar->winrct.ymin + walk->center_mval[1]); +#ifdef USE_TABLET_SUPPORT + if (walk->is_cursor_absolute == false) +#endif + { + /* center the mouse */ + WM_cursor_warp( + win, + walk->ar->winrct.xmin + walk->center_mval[0], + walk->ar->winrct.ymin + walk->center_mval[1]); + } if (walk->state == WALK_CONFIRM) { MEM_freeN(walk); @@ -618,6 +640,27 @@ static void walkEvent(bContext *C, wmOperator *UNUSED(op), WalkInfo *walk, const } else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { +#ifdef USE_TABLET_SUPPORT + if (walk->is_cursor_first) { + /* wait until we get the 'warp' event */ + if ((walk->center_mval[0] == event->mval[0]) && + (walk->center_mval[1] == event->mval[1])) + { + walk->is_cursor_first = false; + } + return; + } + + if ((walk->is_cursor_absolute == false) && WM_event_is_absolute(event)) { + walk->is_cursor_absolute = true; + copy_v2_v2_int(walk->prev_mval, event->mval); + copy_v2_v2_int(walk->center_mval, event->mval); + /* without this we can't turn 180d */ + CLAMP_MIN(walk->mouse_speed, 4.0f); + } +#endif /* USE_TABLET_SUPPORT */ + + walk->moffset[0] += event->mval[0] - walk->prev_mval[0]; walk->moffset[1] += event->mval[1] - walk->prev_mval[1]; @@ -628,6 +671,12 @@ static void walkEvent(bContext *C, wmOperator *UNUSED(op), WalkInfo *walk, const { walk->redraw = true; +#ifdef USE_TABLET_SUPPORT + if (walk->is_cursor_absolute) { + /* pass */ + } + else +#endif if (wm_event_is_last_mousemove(event)) { wmWindow *win = CTX_wm_window(C); |