Merge remote-tracking branch 'origin/master' into blender2.8
[blender.git] / source / blender / editors / space_view3d / view3d_draw.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2008 Blender Foundation.
19  * All rights reserved.
20  *
21  * 
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/space_view3d/view3d_draw.c
28  *  \ingroup spview3d
29  */
30
31 #include <math.h>
32
33 #include "BIF_gl.h"
34 #include "BIF_glutil.h"
35
36 #include "BKE_camera.h"
37 #include "BKE_context.h"
38 #include "BKE_global.h"
39 #include "BKE_key.h"
40 #include "BKE_scene.h"
41 #include "BKE_object.h"
42 #include "BKE_paint.h"
43 #include "BKE_unit.h"
44
45 #include "BLF_api.h"
46
47 #include "BLI_listbase.h"
48 #include "BLI_math.h"
49 #include "BLI_rect.h"
50 #include "BLI_string.h"
51 #include "BLI_threads.h"
52 #include "BLI_jitter.h"
53
54 #include "BLT_translation.h"
55
56 #include "DNA_armature_types.h"
57 #include "DNA_brush_types.h"
58 #include "DNA_camera_types.h"
59 #include "DNA_key_types.h"
60 #include "DNA_mesh_types.h"
61 #include "DNA_object_types.h"
62 #include "DNA_view3d_types.h"
63 #include "DNA_windowmanager_types.h"
64
65 #include "DRW_engine.h"
66
67 #include "ED_keyframing.h"
68 #include "ED_armature.h"
69 #include "ED_keyframing.h"
70 #include "ED_gpencil.h"
71 #include "ED_screen.h"
72 #include "ED_transform.h"
73 #include "ED_gpencil.h"
74
75 #include "DEG_depsgraph_query.h"
76
77 #include "GPU_draw.h"
78 #include "GPU_matrix.h"
79 #include "GPU_immediate.h"
80 #include "GPU_immediate_util.h"
81 #include "GPU_material.h"
82 #include "GPU_viewport.h"
83 #include "GPU_compositing.h"
84
85 #include "MEM_guardedalloc.h"
86
87 #include "UI_interface.h"
88 #include "UI_resources.h"
89
90 #include "RE_engine.h"
91
92 #include "WM_api.h"
93 #include "WM_types.h"
94
95 #include "IMB_imbuf.h"
96 #include "IMB_imbuf_types.h"
97
98 #include "view3d_intern.h"  /* own include */
99
100 /* prototypes */
101 static void draw_all_objects(const bContext *C, ARegion *ar, const bool only_depth, const bool use_depth);
102 static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d);
103
104 typedef struct DrawData {
105         rcti border_rect;
106         bool render_border;
107         bool clip_border;
108         bool is_render;
109         GPUViewport *viewport;
110 } DrawData;
111
112 static void view3d_draw_data_init(const bContext *C, ARegion *ar, RegionView3D *rv3d, DrawData *draw_data)
113 {
114         Scene *scene = CTX_data_scene(C);
115         View3D *v3d = CTX_wm_view3d(C);
116
117         draw_data->is_render = (v3d->drawtype == OB_RENDER);
118
119         draw_data->render_border = ED_view3d_calc_render_border(scene, v3d, ar, &draw_data->border_rect);
120         draw_data->clip_border = (draw_data->render_border && !BLI_rcti_compare(&ar->drawrct, &draw_data->border_rect));
121
122         draw_data->viewport = rv3d->viewport;
123 }
124
125 /* ******************** general functions ***************** */
126
127 static bool use_depth_doit(Scene *scene, View3D *v3d)
128 {
129         if (v3d->drawtype > OB_WIRE)
130                 return true;
131
132         /* special case (depth for wire color) */
133         if (v3d->drawtype <= OB_WIRE) {
134                 if (scene->obedit && scene->obedit->type == OB_MESH) {
135                         Mesh *me = scene->obedit->data;
136                         if (me->drawflag & ME_DRAWEIGHT) {
137                                 return true;
138                         }
139                 }
140         }
141         return false;
142 }
143
144 static bool use_depth(const bContext *C)
145 {
146         View3D *v3d = CTX_wm_view3d(C);
147         Scene *scene = CTX_data_scene(C);
148         return use_depth_doit(scene, v3d);
149 }
150
151 /**
152  * \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore
153  */
154 void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
155 {
156         RegionView3D *rv3d = ar->regiondata;
157
158
159         /* setup window matrices */
160         if (winmat)
161                 copy_m4_m4(rv3d->winmat, winmat);
162         else
163                 view3d_winmatrix_set(ar, v3d, NULL);
164
165         /* setup view matrix */
166         if (viewmat)
167                 copy_m4_m4(rv3d->viewmat, viewmat);
168         else
169                 view3d_viewmatrix_set(scene, v3d, rv3d);  /* note: calls BKE_object_where_is_calc for camera... */
170
171         /* update utility matrices */
172         mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
173         invert_m4_m4(rv3d->persinv, rv3d->persmat);
174         invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
175
176         /* calculate GLSL view dependent values */
177
178         /* store window coordinates scaling/offset */
179         if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
180                 rctf cameraborder;
181                 ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false);
182                 rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder);
183                 rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder);
184
185                 rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx;
186                 rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy;
187         }
188         else {
189                 rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f;
190                 rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f;
191         }
192
193         /* calculate pixelsize factor once, is used for lamps and obcenters */
194         {
195                 /* note:  '1.0f / len_v3(v1)'  replaced  'len_v3(rv3d->viewmat[0])'
196                  * because of float point precision problems at large values [#23908] */
197                 float v1[3], v2[3];
198                 float len_px, len_sc;
199
200                 v1[0] = rv3d->persmat[0][0];
201                 v1[1] = rv3d->persmat[1][0];
202                 v1[2] = rv3d->persmat[2][0];
203
204                 v2[0] = rv3d->persmat[0][1];
205                 v2[1] = rv3d->persmat[1][1];
206                 v2[2] = rv3d->persmat[2][1];
207
208                 len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2)));
209                 len_sc = (float)MAX2(ar->winx, ar->winy);
210
211                 rv3d->pixsize = len_px / len_sc;
212         }
213 }
214
215 static void view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
216 {
217         RegionView3D *rv3d = ar->regiondata;
218
219         ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat);
220
221         /* set for opengl */
222         gpuLoadProjectionMatrix(rv3d->winmat);
223         gpuLoadMatrix(rv3d->viewmat);
224 }
225
226 static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d)
227 {
228         if ((scene->r.scemode & R_MULTIVIEW) == 0) {
229                 return false;
230         }
231
232         if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) {
233                 return false;
234         }
235
236         switch (v3d->stereo3d_camera) {
237                 case STEREO_MONO_ID:
238                         return false;
239                         break;
240                 case STEREO_3D_ID:
241                         /* win will be NULL when calling this from the selection or draw loop. */
242                         if ((win == NULL) || (WM_stereo3d_enabled(win, true) == false)) {
243                                 return false;
244                         }
245                         if (((scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) != 0) &&
246                             !BKE_scene_multiview_is_stereo3d(&scene->r))
247                         {
248                                 return false;
249                         }
250                         break;
251                 /* We always need the stereo calculation for left and right cameras. */
252                 case STEREO_LEFT_ID:
253                 case STEREO_RIGHT_ID:
254                 default:
255                         break;
256         }
257         return true;
258 }
259
260
261 /* setup the view and win matrices for the multiview cameras
262  *
263  * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called
264  * we have no winmatrix (i.e., projection matrix) defined at that time.
265  * Since the camera and the camera shift are needed for the winmat calculation
266  * we do a small hack to replace it temporarily so we don't need to change the
267  * view3d)main_region_setup_view() code to account for that.
268  */
269 static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
270 {
271         bool is_left;
272         const char *names[2] = { STEREO_LEFT_NAME, STEREO_RIGHT_NAME };
273         const char *viewname;
274
275         /* show only left or right camera */
276         if (v3d->stereo3d_camera != STEREO_3D_ID)
277                 v3d->multiview_eye = v3d->stereo3d_camera;
278
279         is_left = v3d->multiview_eye == STEREO_LEFT_ID;
280         viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID];
281
282         /* update the viewport matrices with the new camera */
283         if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
284                 Camera *data;
285                 float viewmat[4][4];
286                 float shiftx;
287
288                 data = (Camera *)v3d->camera->data;
289                 shiftx = data->shiftx;
290
291                 BLI_lock_thread(LOCK_VIEW3D);
292                 data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname);
293
294                 BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
295                 view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL);
296
297                 data->shiftx = shiftx;
298                 BLI_unlock_thread(LOCK_VIEW3D);
299         }
300         else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
301                 float viewmat[4][4];
302                 Object *view_ob = v3d->camera;
303                 Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
304
305                 BLI_lock_thread(LOCK_VIEW3D);
306                 v3d->camera = camera;
307
308                 BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
309                 view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL);
310
311                 v3d->camera = view_ob;
312                 BLI_unlock_thread(LOCK_VIEW3D);
313         }
314 }
315
316 /**
317  * Set the correct matrices
318  */
319 void ED_view3d_draw_setup_view(wmWindow *win, Scene *scene, ARegion *ar, View3D *v3d, float viewmat[4][4], float winmat[4][4])
320 {
321         RegionView3D *rv3d = ar->regiondata;
322
323         /* Setup the view matrix. */
324         if (view3d_stereo3d_active(win, scene, v3d, rv3d)) {
325                 view3d_stereo3d_setup(scene, v3d, ar);
326         }
327         else {
328                 view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
329         }
330 }
331
332 /* ******************** debug ***************** */
333
334 #define VIEW3D_DRAW_DEBUG 1
335 /* TODO: expand scope of this flag so UI reflects the underlying code */
336
337 #if VIEW3D_DRAW_DEBUG
338
339 static void view3d_draw_debug_store_depth(ARegion *UNUSED(ar), DrawData *draw_data)
340 {
341         GPUViewport *viewport = draw_data->viewport;
342         GLint viewport_size[4];
343         glGetIntegerv(GL_VIEWPORT, viewport_size);
344
345         const int x = viewport_size[0];
346         const int y = viewport_size[1];
347         const int w = viewport_size[2];
348         const int h = viewport_size[3];
349
350         if (GPU_viewport_debug_depth_is_valid(viewport)) {
351                 if ((GPU_viewport_debug_depth_width(viewport) != w) ||
352                     (GPU_viewport_debug_depth_height(viewport) != h))
353                 {
354                         GPU_viewport_debug_depth_free(viewport);
355                 }
356         }
357
358         if (!GPU_viewport_debug_depth_is_valid(viewport)) {
359                 char error[256];
360                 if (!GPU_viewport_debug_depth_create(viewport, w, h, error)) {
361                         fprintf(stderr, "Failed to create depth buffer for debug: %s\n", error);
362                         return;
363                 }
364         }
365
366         GPU_viewport_debug_depth_store(viewport, x, y);
367 }
368
369 static void view3d_draw_debug_post_solid(const bContext *C, ARegion *ar, DrawData *draw_data)
370 {
371         View3D *v3d = CTX_wm_view3d(C);
372
373         if ((v3d->tmp_compat_flag & V3D_DEBUG_SHOW_SCENE_DEPTH) != 0) {
374                 view3d_draw_debug_store_depth(ar, draw_data);
375         }
376 }
377
378 static void view3d_draw_debug(const bContext *C, ARegion *ar, DrawData *draw_data)
379 {
380         View3D *v3d = CTX_wm_view3d(C);
381
382         if ((v3d->tmp_compat_flag & V3D_DEBUG_SHOW_COMBINED_DEPTH) != 0) {
383                 /* store */
384                 view3d_draw_debug_store_depth(ar, draw_data);
385         }
386
387         if (((v3d->tmp_compat_flag & V3D_DEBUG_SHOW_SCENE_DEPTH) != 0) ||
388             ((v3d->tmp_compat_flag & V3D_DEBUG_SHOW_COMBINED_DEPTH) != 0))
389         {
390                 /* draw */
391                 if (GPU_viewport_debug_depth_is_valid(draw_data->viewport)) {
392                         GPU_viewport_debug_depth_draw(draw_data->viewport, v3d->debug.znear, v3d->debug.zfar);
393                 }
394         }
395         else {
396                 /* cleanup */
397                 GPU_viewport_debug_depth_free(draw_data->viewport);
398         }
399 }
400
401 #endif /* VIEW3D_DRAW_DEBUG */
402
403 /* ******************** view border ***************** */
404
405 static void view3d_camera_border(
406         const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
407         rctf *r_viewborder, const bool no_shift, const bool no_zoom)
408 {
409         CameraParams params;
410         rctf rect_view, rect_camera;
411
412         /* get viewport viewplane */
413         BKE_camera_params_init(&params);
414         BKE_camera_params_from_view3d(&params, v3d, rv3d);
415         if (no_zoom)
416                 params.zoom = 1.0f;
417         BKE_camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
418         rect_view = params.viewplane;
419
420         /* get camera viewplane */
421         BKE_camera_params_init(&params);
422         /* fallback for non camera objects */
423         params.clipsta = v3d->near;
424         params.clipend = v3d->far;
425         BKE_camera_params_from_object(&params, v3d->camera);
426         if (no_shift) {
427                 params.shiftx = 0.0f;
428                 params.shifty = 0.0f;
429         }
430         BKE_camera_params_compute_viewplane(&params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
431         rect_camera = params.viewplane;
432
433         /* get camera border within viewport */
434         r_viewborder->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
435         r_viewborder->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
436         r_viewborder->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
437         r_viewborder->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
438 }
439
440 void ED_view3d_calc_camera_border_size(
441         const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
442         float r_size[2])
443 {
444         rctf viewborder;
445
446         view3d_camera_border(scene, ar, v3d, rv3d, &viewborder, true, true);
447         r_size[0] = BLI_rctf_size_x(&viewborder);
448         r_size[1] = BLI_rctf_size_y(&viewborder);
449 }
450
451 void ED_view3d_calc_camera_border(
452         const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
453         rctf *r_viewborder, const bool no_shift)
454 {
455         view3d_camera_border(scene, ar, v3d, rv3d, r_viewborder, no_shift, false);
456 }
457
458 static void drawviewborder_grid3(uint shdr_pos, float x1, float x2, float y1, float y2, float fac)
459 {
460         float x3, y3, x4, y4;
461
462         x3 = x1 + fac * (x2 - x1);
463         y3 = y1 + fac * (y2 - y1);
464         x4 = x1 + (1.0f - fac) * (x2 - x1);
465         y4 = y1 + (1.0f - fac) * (y2 - y1);
466
467         immBegin(PRIM_LINES, 8);
468
469         immVertex2f(shdr_pos, x1, y3);
470         immVertex2f(shdr_pos, x2, y3);
471
472         immVertex2f(shdr_pos, x1, y4);
473         immVertex2f(shdr_pos, x2, y4);
474
475         immVertex2f(shdr_pos, x3, y1);
476         immVertex2f(shdr_pos, x3, y2);
477
478         immVertex2f(shdr_pos, x4, y1);
479         immVertex2f(shdr_pos, x4, y2);
480
481         immEnd();
482 }
483
484 /* harmonious triangle */
485 static void drawviewborder_triangle(
486         uint shdr_pos, float x1, float x2, float y1, float y2, const char golden, const char dir)
487 {
488         float ofs;
489         float w = x2 - x1;
490         float h = y2 - y1;
491
492         immBegin(PRIM_LINES, 6);
493
494         if (w > h) {
495                 if (golden) {
496                         ofs = w * (1.0f - (1.0f / 1.61803399f));
497                 }
498                 else {
499                         ofs = h * (h / w);
500                 }
501                 if (dir == 'B') SWAP(float, y1, y2);
502
503                 immVertex2f(shdr_pos, x1, y1);
504                 immVertex2f(shdr_pos, x2, y2);
505
506                 immVertex2f(shdr_pos, x2, y1);
507                 immVertex2f(shdr_pos, x1 + (w - ofs), y2);
508
509                 immVertex2f(shdr_pos, x1, y2);
510                 immVertex2f(shdr_pos, x1 + ofs, y1);
511         }
512         else {
513                 if (golden) {
514                         ofs = h * (1.0f - (1.0f / 1.61803399f));
515                 }
516                 else {
517                         ofs = w * (w / h);
518                 }
519                 if (dir == 'B') SWAP(float, x1, x2);
520
521                 immVertex2f(shdr_pos, x1, y1);
522                 immVertex2f(shdr_pos, x2, y2);
523
524                 immVertex2f(shdr_pos, x2, y1);
525                 immVertex2f(shdr_pos, x1, y1 + ofs);
526
527                 immVertex2f(shdr_pos, x1, y2);
528                 immVertex2f(shdr_pos, x2, y1 + (h - ofs));
529         }
530
531         immEnd();
532 }
533
534 static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
535 {
536         float x1, x2, y1, y2;
537         float x1i, x2i, y1i, y2i;
538
539         rctf viewborder;
540         Camera *ca = NULL;
541         RegionView3D *rv3d = ar->regiondata;
542
543         if (v3d->camera == NULL)
544                 return;
545         if (v3d->camera->type == OB_CAMERA)
546                 ca = v3d->camera->data;
547
548         ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
549         /* the offsets */
550         x1 = viewborder.xmin;
551         y1 = viewborder.ymin;
552         x2 = viewborder.xmax;
553         y2 = viewborder.ymax;
554
555         glLineWidth(1.0f);
556
557         /* apply offsets so the real 3D camera shows through */
558
559         /* note: quite un-scientific but without this bit extra
560          * 0.0001 on the lower left the 2D border sometimes
561          * obscures the 3D camera border */
562         /* note: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticeable
563          * but keep it here in case we need to remove the workaround */
564         x1i = (int)(x1 - 1.0001f);
565         y1i = (int)(y1 - 1.0001f);
566         x2i = (int)(x2 + (1.0f - 0.0001f));
567         y2i = (int)(y2 + (1.0f - 0.0001f));
568
569         uint shdr_pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
570
571         /* First, solid lines. */
572         {
573                 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
574
575                 /* passepartout, specified in camera edit buttons */
576                 if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) {
577                         const float winx = (ar->winx + 1);
578                         const float winy = (ar->winy + 1);
579
580                         float alpha = 1.0f;
581
582                         if (ca->passepartalpha != 1.0f) {
583                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
584                                 glEnable(GL_BLEND);
585                                 alpha = ca->passepartalpha;
586                         }
587
588                         immUniformColor4f(0.0f, 0.0f, 0.0f, alpha);
589
590                         if (x1i > 0.0f)
591                                 immRectf(shdr_pos, 0.0f, winy, x1i, 0.0f);
592                         if (x2i < winx)
593                                 immRectf(shdr_pos, x2i, winy, winx, 0.0f);
594                         if (y2i < winy)
595                                 immRectf(shdr_pos, x1i, winy, x2i, y2i);
596                         if (y2i > 0.0f)
597                                 immRectf(shdr_pos, x1i, y1i, x2i, 0.0f);
598
599                         glDisable(GL_BLEND);
600                 }
601
602                 immUniformThemeColor(TH_BACK);
603                 imm_draw_line_box(shdr_pos, x1i, y1i, x2i, y2i);
604
605 #ifdef VIEW3D_CAMERA_BORDER_HACK
606                 if (view3d_camera_border_hack_test == true) {
607                         immUniformColor3ubv(view3d_camera_border_hack_col);
608                         imm_draw_line_box(shdr_pos, x1i + 1, y1i + 1, x2i - 1, y2i - 1);
609                         view3d_camera_border_hack_test = false;
610                 }
611 #endif
612
613                 immUnbindProgram();
614         }
615
616         /* And now, the dashed lines! */
617         {
618                 immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_COLOR);
619
620                 float viewport_size[4];
621                 glGetFloatv(GL_VIEWPORT, viewport_size);
622                 immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
623
624                 immUniform1i("num_colors", 0);  /* "simple" mode */
625                 immUniform1f("dash_width", 6.0f);
626                 immUniform1f("dash_factor", 0.5f);
627
628                 /* outer line not to confuse with object selection */
629                 if (v3d->flag2 & V3D_LOCK_CAMERA) {
630                         immUniformThemeColor(TH_REDALERT);
631                         imm_draw_line_box(shdr_pos, x1i - 1, y1i - 1, x2i + 1, y2i + 1);
632                 }
633
634                 immUniformThemeColor(TH_VIEW_OVERLAY);
635                 imm_draw_line_box(shdr_pos, x1i, y1i, x2i, y2i);
636
637                 /* border */
638                 if (scene->r.mode & R_BORDER) {
639                         float x3, y3, x4, y4;
640
641                         x3 = floorf(x1 + (scene->r.border.xmin * (x2 - x1))) - 1;
642                         y3 = floorf(y1 + (scene->r.border.ymin * (y2 - y1))) - 1;
643                         x4 = floorf(x1 + (scene->r.border.xmax * (x2 - x1))) + (U.pixelsize - 1);
644                         y4 = floorf(y1 + (scene->r.border.ymax * (y2 - y1))) + (U.pixelsize - 1);
645
646                         immUniformColor3f(1.0f, 0.25f, 0.25f);
647                         imm_draw_line_box(shdr_pos, x3, y3, x4, y4);
648                 }
649
650                 /* safety border */
651                 if (ca) {
652                         immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f);
653
654                         if (ca->dtx & CAM_DTX_CENTER) {
655                                 float x3, y3;
656
657                                 x3 = x1 + 0.5f * (x2 - x1);
658                                 y3 = y1 + 0.5f * (y2 - y1);
659
660                                 immBegin(PRIM_LINES, 4);
661
662                                 immVertex2f(shdr_pos, x1, y3);
663                                 immVertex2f(shdr_pos, x2, y3);
664
665                                 immVertex2f(shdr_pos, x3, y1);
666                                 immVertex2f(shdr_pos, x3, y2);
667
668                                 immEnd();
669                         }
670
671                         if (ca->dtx & CAM_DTX_CENTER_DIAG) {
672                                 immBegin(PRIM_LINES, 4);
673
674                                 immVertex2f(shdr_pos, x1, y1);
675                                 immVertex2f(shdr_pos, x2, y2);
676
677                                 immVertex2f(shdr_pos, x1, y2);
678                                 immVertex2f(shdr_pos, x2, y1);
679
680                                 immEnd();
681                         }
682
683                         if (ca->dtx & CAM_DTX_THIRDS) {
684                                 drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f / 3.0f);
685                         }
686
687                         if (ca->dtx & CAM_DTX_GOLDEN) {
688                                 drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f));
689                         }
690
691                         if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) {
692                                 drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'A');
693                         }
694
695                         if (ca->dtx & CAM_DTX_GOLDEN_TRI_B) {
696                                 drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'B');
697                         }
698
699                         if (ca->dtx & CAM_DTX_HARMONY_TRI_A) {
700                                 drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'A');
701                         }
702
703                         if (ca->dtx & CAM_DTX_HARMONY_TRI_B) {
704                                 drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'B');
705                         }
706
707                         if (ca->flag & CAM_SHOW_SAFE_MARGINS) {
708                                 UI_draw_safe_areas(shdr_pos, x1, x2, y1, y2,
709                                                    scene->safe_areas.title, scene->safe_areas.action);
710
711                                 if (ca->flag & CAM_SHOW_SAFE_CENTER) {
712                                         UI_draw_safe_areas(shdr_pos, x1, x2, y1, y2,
713                                                            scene->safe_areas.title_center, scene->safe_areas.action_center);
714                                 }
715                         }
716                 }
717
718                 if (ca->flag & CAM_SHOWSENSOR) {
719                         /* determine sensor fit, and get sensor x/y, for auto fit we
720                          * assume and square sensor and only use sensor_x */
721                         float sizex = scene->r.xsch * scene->r.xasp;
722                         float sizey = scene->r.ysch * scene->r.yasp;
723                         int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, sizex, sizey);
724                         float sensor_x = ca->sensor_x;
725                         float sensor_y = (ca->sensor_fit == CAMERA_SENSOR_FIT_AUTO) ? ca->sensor_x : ca->sensor_y;
726
727                         /* determine sensor plane */
728                         rctf rect;
729
730                         if (sensor_fit == CAMERA_SENSOR_FIT_HOR) {
731                                 float sensor_scale = (x2i - x1i) / sensor_x;
732                                 float sensor_height = sensor_scale * sensor_y;
733
734                                 rect.xmin = x1i;
735                                 rect.xmax = x2i;
736                                 rect.ymin = (y1i + y2i) * 0.5f - sensor_height * 0.5f;
737                                 rect.ymax = rect.ymin + sensor_height;
738                         }
739                         else {
740                                 float sensor_scale = (y2i - y1i) / sensor_y;
741                                 float sensor_width = sensor_scale * sensor_x;
742
743                                 rect.xmin = (x1i + x2i) * 0.5f - sensor_width * 0.5f;
744                                 rect.xmax = rect.xmin + sensor_width;
745                                 rect.ymin = y1i;
746                                 rect.ymax = y2i;
747                         }
748
749                         /* draw */
750                         immUniformThemeColorShade(TH_VIEW_OVERLAY, 100);
751
752                         /* TODO Was using UI_draw_roundbox_4fv(false, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color).
753                          * We'll probably need a new imm_draw_line_roundbox_dashed dor that - though in practice the
754                          * 2.0f round corner effect was nearly not visible anyway... */
755                         imm_draw_line_box(shdr_pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
756                 }
757
758                 immUnbindProgram();
759         }
760
761         /* camera name - draw in highlighted text color */
762         if (ca && (ca->flag & CAM_SHOWNAME)) {
763                 UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
764                 BLF_draw_default(x1i, y1i - (0.7f * U.widget_unit), 0.0f,
765                                  v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2);
766         }
767 }
768
769 static void drawrenderborder(ARegion *ar, View3D *v3d)
770 {
771         /* use the same program for everything */
772         uint shdr_pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
773
774         glLineWidth(1.0f);
775
776         immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_COLOR);
777
778         float viewport_size[4];
779         glGetFloatv(GL_VIEWPORT, viewport_size);
780         immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
781
782         immUniform1i("num_colors", 0);  /* "simple" mode */
783         immUniform4f("color", 1.0f, 0.25f, 0.25f, 1.0f);
784         immUniform1f("dash_width", 6.0f);
785         immUniform1f("dash_factor", 0.5f);
786
787         imm_draw_line_box(shdr_pos,
788                           v3d->render_border.xmin * ar->winx, v3d->render_border.ymin * ar->winy,
789                           v3d->render_border.xmax * ar->winx, v3d->render_border.ymax * ar->winy);
790
791         immUnbindProgram();
792 }
793
794 void ED_view3d_draw_depth(
795         struct Depsgraph *graph,
796         ARegion *ar, View3D *v3d, bool alphaoverride)
797 {
798         Scene *scene = DAG_get_scene(graph);
799         RegionView3D *rv3d = ar->regiondata;
800
801         short zbuf = v3d->zbuf;
802         short flag = v3d->flag;
803         float glalphaclip = U.glalphaclip;
804         int obcenter_dia = U.obcenter_dia;
805         /* temp set drawtype to solid */
806         /* Setting these temporarily is not nice */
807         v3d->flag &= ~V3D_SELECT_OUTLINE;
808         U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */
809         U.obcenter_dia = 0;
810
811         ED_view3d_draw_setup_view(NULL, scene, ar, v3d, NULL, NULL);
812
813         glClear(GL_DEPTH_BUFFER_BIT);
814
815         if (rv3d->rflag & RV3D_CLIPPING) {
816                 ED_view3d_clipping_set(rv3d);
817         }
818         /* get surface depth without bias */
819         rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
820
821         v3d->zbuf = true;
822         glEnable(GL_DEPTH_TEST);
823
824 #ifdef WITH_OPENGL_LEGACY
825         if (IS_VIEWPORT_LEGACY(vc->v3d)) {
826                 /* temp, calls into view3d_draw_legacy.c */
827                 ED_view3d_draw_depth_loop(scene, ar, v3d);
828         }
829         else
830 #endif /* WITH_OPENGL_LEGACY */
831         {
832                 DRW_draw_depth_loop(graph, ar, v3d);
833         }
834
835         if (rv3d->rflag & RV3D_CLIPPING) {
836                 ED_view3d_clipping_disable();
837         }
838         rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
839
840         v3d->zbuf = zbuf;
841         if (!v3d->zbuf) glDisable(GL_DEPTH_TEST);
842
843         U.glalphaclip = glalphaclip;
844         v3d->flag = flag;
845         U.obcenter_dia = obcenter_dia;
846 }
847
848 /* ******************** offline engine ***************** */
849
850 static bool view3d_draw_render_draw(const bContext *C, Scene *scene,
851     ARegion *ar, View3D *UNUSED(v3d),
852     bool clip_border, const rcti *border_rect)
853 {
854         RegionView3D *rv3d = ar->regiondata;
855         RenderEngineType *type;
856         GLint scissor[4];
857
858         /* create render engine */
859         if (!rv3d->render_engine) {
860                 RenderEngine *engine;
861
862                 type = RE_engines_find(scene->r.engine);
863
864                 if (!(type->view_update && type->render_to_view))
865                         return false;
866
867                 engine = RE_engine_create_ex(type, true);
868
869                 engine->tile_x = scene->r.tilex;
870                 engine->tile_y = scene->r.tiley;
871
872                 type->view_update(engine, C);
873
874                 rv3d->render_engine = engine;
875         }
876
877         /* rendered draw */
878         gpuPushMatrix();
879         float original_proj[4][4];
880         gpuGetProjectionMatrix(original_proj);
881         ED_region_pixelspace(ar);
882
883         if (clip_border) {
884                 /* for border draw, we only need to clear a subset of the 3d view */
885                 if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) {
886                         glGetIntegerv(GL_SCISSOR_BOX, scissor);
887                         glScissor(border_rect->xmin, border_rect->ymin,
888                                 BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect));
889                 }
890                 else {
891                         return false;
892                 }
893         }
894
895         /* don't change depth buffer */
896         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
897         glClear(GL_COLOR_BUFFER_BIT); /* is this necessary? -- merwin */
898
899         /* render result draw */
900         type = rv3d->render_engine->type;
901         type->render_to_view(rv3d->render_engine, C);
902
903         if (clip_border) {
904                 /* restore scissor as it was before */
905                 glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
906         }
907
908         gpuLoadProjectionMatrix(original_proj);
909         gpuPopMatrix();
910
911         return true;
912 }
913
914 /* ******************** background plates ***************** */
915
916 static void view3d_draw_background_gradient(void)
917 {
918         /* TODO: finish 2D API & draw background with that */
919
920         VertexFormat *format = immVertexFormat();
921         unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
922         unsigned int color = VertexFormat_add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
923         unsigned char col_hi[3], col_lo[3];
924
925         immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
926
927         UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo);
928         UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi);
929
930         immBegin(PRIM_TRIANGLE_FAN, 4);
931         immAttrib3ubv(color, col_lo);
932         immVertex2f(pos, -1.0f, -1.0f);
933         immVertex2f(pos, 1.0f, -1.0f);
934
935         immAttrib3ubv(color, col_hi);
936         immVertex2f(pos, 1.0f, 1.0f);
937         immVertex2f(pos, -1.0f, 1.0f);
938         immEnd();
939
940         immUnbindProgram();
941 }
942
943 static void view3d_draw_background_none(void)
944 {
945         UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
946         glClear(GL_COLOR_BUFFER_BIT);
947 }
948
949 static void view3d_draw_background_world(Scene *scene, View3D *v3d, RegionView3D *rv3d)
950 {
951         if (scene->world) {
952                 GPUMaterial *gpumat = GPU_material_world(scene, scene->world);
953
954                 /* calculate full shader for background */
955                 GPU_material_bind(gpumat, 1, 1, 1.0f, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0));
956
957                 if (GPU_material_bound(gpumat)) {
958                         /* TODO viewport (dfelinto): GPU_material_bind relies on immediate mode,
959                          * we can't get rid of the following code without a bigger refactor
960                          * or we dropping this functionality. */
961
962                         glBegin(GL_TRIANGLE_STRIP);
963                         glVertex2f(-1.0f, -1.0f);
964                         glVertex2f(1.0f, -1.0f);
965                         glVertex2f(-1.0f, 1.0f);
966                         glVertex2f(1.0f, 1.0f);
967                         glEnd();
968
969                         GPU_material_unbind(gpumat);
970                         return;
971                 }
972         }
973
974         /* if any of the above fails */
975         view3d_draw_background_none();
976 }
977
978 /* ******************** solid plates ***************** */
979
980 /**
981  * Clear the buffer and draw the proper shader
982  */
983 static void view3d_draw_background(const bContext *C)
984 {
985         Scene *scene = CTX_data_scene(C);
986         View3D *v3d = CTX_wm_view3d(C);
987         RegionView3D *rv3d = CTX_wm_region_view3d(C);
988
989         /* Background functions do not read or write depth, but they do clear or completely
990          * overwrite color buffer.
991          */
992
993         switch (v3d->debug.background) {
994                 case V3D_DEBUG_BACKGROUND_WORLD:
995                         view3d_draw_background_world(scene, v3d, rv3d);
996                         break;
997                 case V3D_DEBUG_BACKGROUND_GRADIENT:
998                         view3d_draw_background_gradient();
999                         break;
1000                 case V3D_DEBUG_BACKGROUND_NONE:
1001                 default:
1002                         view3d_draw_background_none();
1003         }
1004 }
1005
1006 /**
1007  *
1008  */
1009 static void view3d_draw_render_solid_surfaces(const bContext *C, ARegion *ar, const bool UNUSED(run_screen_shaders))
1010 {
1011         /* TODO viewport */
1012         draw_all_objects(C, ar, false, use_depth(C));
1013 }
1014
1015 /**
1016  *
1017  */
1018 static void view3d_draw_render_transparent_surfaces(const bContext *UNUSED(C))
1019 {
1020         /* TODO viewport */
1021 }
1022
1023 /**
1024  *
1025  */
1026 static void view3d_draw_post_draw(const bContext *UNUSED(C))
1027 {
1028         /* TODO viewport */
1029 }
1030
1031 /* ******************** geometry overlay ***************** */
1032
1033 /**
1034  * Front/back wire frames
1035  */
1036 static void view3d_draw_wire_plates(const bContext *UNUSED(C))
1037 {
1038         /* TODO viewport */
1039 }
1040
1041 /**
1042  * Special treatment for selected objects
1043  */
1044 static void view3d_draw_outline_plates(const bContext *UNUSED(C))
1045 {
1046         /* TODO viewport */
1047 }
1048
1049 /* ******************** other elements ***************** */
1050
1051
1052 #define DEBUG_GRID 0
1053
1054 static void gridline_range(double x0, double dx, double max, int *r_first, int *r_count)
1055 {
1056         /* determine range of gridlines that appear in this Area -- similar calc but separate ranges for x & y
1057          * x0 is gridline 0, the axis in screen space
1058          * Area covers [0 .. max) pixels */
1059
1060         int first = (int)ceil(-x0 / dx);
1061         int last = (int)floor((max - x0) / dx);
1062
1063         if (first <= last) {
1064                 *r_first = first;
1065                 *r_count = last - first + 1;
1066         }
1067         else {
1068                 *r_first = 0;
1069                 *r_count = 0;
1070         }
1071
1072 #if DEBUG_GRID
1073         printf("   first %d * dx = %f\n", first, x0 + first * dx);
1074         printf("   last %d * dx = %f\n", last, x0 + last * dx);
1075         printf("   count = %d\n", *count_out);
1076 #endif
1077 }
1078
1079 static int gridline_count(ARegion *ar, double x0, double y0, double dx)
1080 {
1081         /* x0 & y0 establish the "phase" of the grid within this 2D region
1082          * dx is the frequency, shared by x & y directions
1083          * pass in dx of smallest (highest precision) grid we want to draw */
1084
1085 #if DEBUG_GRID
1086         printf("  %s(%f, %f, dx:%f)\n", __FUNCTION__, x0, y0, dx);
1087 #endif
1088
1089         int first, x_ct, y_ct;
1090
1091         gridline_range(x0, dx, ar->winx, &first, &x_ct);
1092         gridline_range(y0, dx, ar->winy, &first, &y_ct);
1093
1094         int total_ct = x_ct + y_ct;
1095
1096 #if DEBUG_GRID
1097         printf("   %d + %d = %d gridlines\n", x_ct, y_ct, total_ct);
1098 #endif
1099
1100         return total_ct;
1101 }
1102
1103 static bool drawgrid_draw(ARegion *ar, double x0, double y0, double dx, int skip_mod, unsigned pos, unsigned col, GLubyte col_value[3])
1104 {
1105         /* skip every skip_mod lines relative to each axis; they will be overlaid by another drawgrid_draw
1106          * always skip exact x0 & y0 axes; they will be drawn later in color
1107          *
1108          * set grid color once, just before the first line is drawn
1109          * it's harmless to set same color for every line, or every vertex
1110          * but if no lines are drawn, color must not be set! */
1111
1112 #if DEBUG_GRID
1113         printf("  %s(%f, %f, dx:%f, skip_mod:%d)\n", __FUNCTION__, x0, y0, dx, skip_mod);
1114 #endif
1115
1116         const float x_max = (float)ar->winx;
1117         const float y_max = (float)ar->winy;
1118
1119         int first, ct;
1120         int x_ct = 0, y_ct = 0; /* count of lines actually drawn */
1121         int lines_skipped_for_next_unit = 0;
1122
1123         /* draw vertical lines */
1124         gridline_range(x0, dx, x_max, &first, &ct);
1125
1126         for (int i = first; i < first + ct; ++i) {
1127                 if (i == 0)
1128                         continue;
1129                 else if (skip_mod && (i % skip_mod) == 0) {
1130                         ++lines_skipped_for_next_unit;
1131                         continue;
1132                 }
1133
1134                 if (x_ct == 0)
1135                         immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
1136
1137                 float x = (float)(x0 + i * dx);
1138                 immVertex2f(pos, x, 0.0f);
1139                 immVertex2f(pos, x, y_max);
1140                 ++x_ct;
1141         }
1142
1143         /* draw horizontal lines */
1144         gridline_range(y0, dx, y_max, &first, &ct);
1145
1146         for (int i = first; i < first + ct; ++i) {
1147                 if (i == 0)
1148                         continue;
1149                 else if (skip_mod && (i % skip_mod) == 0) {
1150                         ++lines_skipped_for_next_unit;
1151                         continue;
1152                 }
1153
1154                 if (x_ct + y_ct == 0)
1155                         immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
1156
1157                 float y = (float)(y0 + i * dx);
1158                 immVertex2f(pos, 0.0f, y);
1159                 immVertex2f(pos, x_max, y);
1160                 ++y_ct;
1161         }
1162
1163 #if DEBUG_GRID
1164         int total_ct = x_ct + y_ct;
1165         printf("    %d + %d = %d gridlines drawn, %d skipped for next unit\n", x_ct, y_ct, total_ct, lines_skipped_for_next_unit);
1166 #endif
1167
1168         return lines_skipped_for_next_unit > 0;
1169 }
1170
1171 #define GRID_MIN_PX_D 6.0
1172 #define GRID_MIN_PX_F 6.0f
1173
1174 static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
1175 {
1176         RegionView3D *rv3d = ar->regiondata;
1177
1178 #if DEBUG_GRID
1179         printf("%s width %d, height %d\n", __FUNCTION__, ar->winx, ar->winy);
1180 #endif
1181
1182         double fx = rv3d->persmat[3][0];
1183         double fy = rv3d->persmat[3][1];
1184         double fw = rv3d->persmat[3][3];
1185
1186         const double wx = 0.5 * ar->winx;  /* use double precision to avoid rounding errors */
1187         const double wy = 0.5 * ar->winy;
1188
1189         double x = wx * fx / fw;
1190         double y = wy * fy / fw;
1191
1192         double vec4[4] = { v3d->grid, v3d->grid, 0.0, 1.0 };
1193         mul_m4_v4d(rv3d->persmat, vec4);
1194         fx = vec4[0];
1195         fy = vec4[1];
1196         fw = vec4[3];
1197
1198         double dx = fabs(x - wx * fx / fw);
1199         if (dx == 0) dx = fabs(y - wy * fy / fw);
1200
1201         x += wx;
1202         y += wy;
1203
1204         /* now x, y, and dx have their final values
1205          * (x,y) is the world origin (0,0,0) mapped to Area-relative screen space
1206          * dx is the distance in pixels between grid lines -- same for horiz or vert grid lines */
1207
1208         glLineWidth(1.0f);
1209
1210 #if 0 /* TODO: write to UI/widget depth buffer, not scene depth */
1211         glDepthMask(GL_FALSE);  /* disable write in zbuffer */
1212 #endif
1213
1214         VertexFormat *format = immVertexFormat();
1215         unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
1216         unsigned int color = VertexFormat_add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
1217
1218         immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
1219
1220         unsigned char col[3], col2[3];
1221         UI_GetThemeColor3ubv(TH_GRID, col);
1222
1223         if (unit->system) {
1224                 const void *usys;
1225                 int len;
1226
1227                 bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len);
1228
1229                 bool first = true;
1230
1231                 if (usys) {
1232                         int i = len;
1233                         while (i--) {
1234                                 double scalar = bUnit_GetScaler(usys, i);
1235
1236                                 double dx_scalar = dx * scalar / (double)unit->scale_length;
1237                                 if (dx_scalar < (GRID_MIN_PX_D * 2.0)) {
1238                                         /* very very small grid items are less useful when dealing with units */
1239                                         continue;
1240                                 }
1241
1242                                 if (first) {
1243                                         first = false;
1244
1245                                         /* Store the smallest drawn grid size units name so users know how big each grid cell is */
1246                                         *grid_unit = bUnit_GetNameDisplay(usys, i);
1247                                         rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length);
1248
1249                                         int gridline_ct = gridline_count(ar, x, y, dx_scalar);
1250                                         if (gridline_ct == 0)
1251                                                 goto drawgrid_cleanup; /* nothing to draw */
1252
1253                                         immBegin(PRIM_LINES, gridline_ct * 2);
1254                                 }
1255
1256                                 float blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar);
1257                                 /* tweak to have the fade a bit nicer */
1258                                 blend_fac = (blend_fac * blend_fac) * 2.0f;
1259                                 CLAMP(blend_fac, 0.3f, 1.0f);
1260
1261                                 UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, blend_fac, col2);
1262
1263                                 const int skip_mod = (i == 0) ? 0 : (int)round(bUnit_GetScaler(usys, i - 1) / scalar);
1264 #if DEBUG_GRID
1265                                 printf("%s %f, ", bUnit_GetNameDisplay(usys, i), scalar);
1266                                 if (i > 0)
1267                                         printf("next unit is %d times larger\n", skip_mod);
1268                                 else
1269                                         printf("largest unit\n");
1270 #endif
1271                                 if (!drawgrid_draw(ar, x, y, dx_scalar, skip_mod, pos, color, col2))
1272                                         break;
1273                         }
1274                 }
1275         }
1276         else {
1277                 const double sublines = v3d->gridsubdiv;
1278                 const float  sublines_fl = v3d->gridsubdiv;
1279
1280                 int grids_to_draw = 2; /* first the faint fine grid, then the bold coarse grid */
1281
1282                 if (dx < GRID_MIN_PX_D) {
1283                         rv3d->gridview *= sublines_fl;
1284                         dx *= sublines;
1285                         if (dx < GRID_MIN_PX_D) {
1286                                 rv3d->gridview *= sublines_fl;
1287                                 dx *= sublines;
1288                                 if (dx < GRID_MIN_PX_D) {
1289                                         rv3d->gridview *= sublines_fl;
1290                                         dx *= sublines;
1291                                         grids_to_draw = (dx < GRID_MIN_PX_D) ? 0 : 1;
1292                                 }
1293                         }
1294                 }
1295                 else {
1296                         if (dx > (GRID_MIN_PX_D * 10.0)) {  /* start blending in */
1297                                 rv3d->gridview /= sublines_fl;
1298                                 dx /= sublines;
1299                                 if (dx > (GRID_MIN_PX_D * 10.0)) {  /* start blending in */
1300                                         rv3d->gridview /= sublines_fl;
1301                                         dx /= sublines;
1302                                         if (dx > (GRID_MIN_PX_D * 10.0)) {
1303                                                 grids_to_draw = 1;
1304                                         }
1305                                 }
1306                         }
1307                 }
1308
1309                 int gridline_ct = gridline_count(ar, x, y, dx);
1310                 if (gridline_ct == 0)
1311                         goto drawgrid_cleanup; /* nothing to draw */
1312
1313                 immBegin(PRIM_LINES, gridline_ct * 2);
1314
1315                 if (grids_to_draw == 2) {
1316                         UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0), col2);
1317                         if (drawgrid_draw(ar, x, y, dx, v3d->gridsubdiv, pos, color, col2))
1318                                 drawgrid_draw(ar, x, y, dx * sublines, 0, pos, color, col);
1319                 }
1320                 else if (grids_to_draw == 1) {
1321                         drawgrid_draw(ar, x, y, dx, 0, pos, color, col);
1322                 }
1323         }
1324
1325         /* draw visible axes */
1326         /* horizontal line */
1327         if (0 <= y && y < ar->winy) {
1328                 UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT) ? 'Y' : 'X');
1329                 immAttrib3ub(color, col2[0], col2[1], col2[2]);
1330                 immVertex2f(pos, 0.0f, y);
1331                 immVertex2f(pos, (float)ar->winx, y);
1332         }
1333
1334         /* vertical line */
1335         if (0 <= x && x < ar->winx) {
1336                 UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM) ? 'Y' : 'Z');
1337                 immAttrib3ub(color, col2[0], col2[1], col2[2]);
1338                 immVertex2f(pos, x, 0.0f);
1339                 immVertex2f(pos, x, (float)ar->winy);
1340         }
1341
1342         immEnd();
1343
1344 drawgrid_cleanup:
1345         immUnbindProgram();
1346
1347 #if 0 /* depth write is left enabled above */
1348         glDepthMask(GL_TRUE);  /* enable write in zbuffer */
1349 #endif
1350 }
1351
1352 #undef DEBUG_GRID
1353 #undef GRID_MIN_PX_D
1354 #undef GRID_MIN_PX_F
1355
1356 static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth)
1357 {
1358         /* draw only if there is something to draw */
1359         if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) {
1360                 /* draw how many lines?
1361                  * trunc(v3d->gridlines / 2) * 4
1362                  * + 2 for xy axes (possibly with special colors)
1363                  * + 1 for z axis (the only line not in xy plane)
1364                  * even v3d->gridlines are honored, odd rounded down */
1365                 const int gridlines = v3d->gridlines / 2;
1366                 const float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
1367                 const float grid = gridlines * grid_scale;
1368
1369                 const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) && gridlines >= 1;
1370
1371                 bool show_axis_x = v3d->gridflag & V3D_SHOW_X;
1372                 bool show_axis_y = v3d->gridflag & V3D_SHOW_Y;
1373                 bool show_axis_z = v3d->gridflag & V3D_SHOW_Z;
1374
1375                 unsigned char col_grid[3], col_axis[3];
1376
1377                 glLineWidth(1.0f);
1378
1379                 UI_GetThemeColor3ubv(TH_GRID, col_grid);
1380
1381                 if (!write_depth)
1382                         glDepthMask(GL_FALSE);
1383
1384                 if (show_floor) {
1385                         const unsigned vertex_ct = 2 * (gridlines * 4 + 2);
1386                         const int sublines = v3d->gridsubdiv;
1387
1388                         unsigned char col_bg[3], col_grid_emphasise[3], col_grid_light[3];
1389
1390                         VertexFormat *format = immVertexFormat();
1391                         unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
1392                         unsigned int color = VertexFormat_add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
1393
1394                         immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
1395
1396                         immBegin(PRIM_LINES, vertex_ct);
1397
1398                         /* draw normal grid lines */
1399                         UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10);
1400
1401                         for (int a = 1; a <= gridlines; a++) {
1402                                 /* skip emphasised divider lines */
1403                                 if (a % sublines != 0) {
1404                                         const float line = a * grid_scale;
1405
1406                                         immAttrib3ubv(color, col_grid_light);
1407
1408                                         immVertex2f(pos, -grid, -line);
1409                                         immVertex2f(pos, +grid, -line);
1410                                         immVertex2f(pos, -grid, +line);
1411                                         immVertex2f(pos, +grid, +line);
1412
1413                                         immVertex2f(pos, -line, -grid);
1414                                         immVertex2f(pos, -line, +grid);
1415                                         immVertex2f(pos, +line, -grid);
1416                                         immVertex2f(pos, +line, +grid);
1417                                 }
1418                         }
1419
1420                         /* draw emphasised grid lines */
1421                         UI_GetThemeColor3ubv(TH_BACK, col_bg);
1422                         /* emphasise division lines lighter instead of darker, if background is darker than grid */
1423                         UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise,
1424                                 (col_grid[0] + col_grid[1] + col_grid[2] + 30 >
1425                                 col_bg[0] + col_bg[1] + col_bg[2]) ? 20 : -10);
1426
1427                         if (sublines <= gridlines) {
1428                                 immAttrib3ubv(color, col_grid_emphasise);
1429
1430                                 for (int a = sublines; a <= gridlines; a += sublines) {
1431                                         const float line = a * grid_scale;
1432
1433                                         immVertex2f(pos, -grid, -line);
1434                                         immVertex2f(pos, +grid, -line);
1435                                         immVertex2f(pos, -grid, +line);
1436                                         immVertex2f(pos, +grid, +line);
1437
1438                                         immVertex2f(pos, -line, -grid);
1439                                         immVertex2f(pos, -line, +grid);
1440                                         immVertex2f(pos, +line, -grid);
1441                                         immVertex2f(pos, +line, +grid);
1442                                 }
1443                         }
1444
1445                         /* draw X axis */
1446                         if (show_axis_x) {
1447                                 show_axis_x = false; /* drawing now, won't need to draw later */
1448                                 UI_make_axis_color(col_grid, col_axis, 'X');
1449                                 immAttrib3ubv(color, col_axis);
1450                         }
1451                         else
1452                                 immAttrib3ubv(color, col_grid_emphasise);
1453
1454                         immVertex2f(pos, -grid, 0.0f);
1455                         immVertex2f(pos, +grid, 0.0f);
1456
1457                         /* draw Y axis */
1458                         if (show_axis_y) {
1459                                 show_axis_y = false; /* drawing now, won't need to draw later */
1460                                 UI_make_axis_color(col_grid, col_axis, 'Y');
1461                                 immAttrib3ubv(color, col_axis);
1462                         }
1463                         else
1464                                 immAttrib3ubv(color, col_grid_emphasise);
1465
1466                         immVertex2f(pos, 0.0f, -grid);
1467                         immVertex2f(pos, 0.0f, +grid);
1468
1469                         immEnd();
1470                         immUnbindProgram();
1471
1472                         /* done with XY plane */
1473                 }
1474
1475                 if (show_axis_x || show_axis_y || show_axis_z) {
1476                         /* draw axis lines -- sometimes grid floor is off, other times we still need to draw the Z axis */
1477
1478                         VertexFormat *format = immVertexFormat();
1479                         unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT);
1480                         unsigned int color = VertexFormat_add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
1481
1482                         immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
1483                         immBegin(PRIM_LINES, (show_axis_x + show_axis_y + show_axis_z) * 2);
1484
1485                         if (show_axis_x) {
1486                                 UI_make_axis_color(col_grid, col_axis, 'X');
1487                                 immAttrib3ubv(color, col_axis);
1488                                 immVertex3f(pos, -grid, 0.0f, 0.0f);
1489                                 immVertex3f(pos, +grid, 0.0f, 0.0f);
1490                         }
1491
1492                         if (show_axis_y) {
1493                                 UI_make_axis_color(col_grid, col_axis, 'Y');
1494                                 immAttrib3ubv(color, col_axis);
1495                                 immVertex3f(pos, 0.0f, -grid, 0.0f);
1496                                 immVertex3f(pos, 0.0f, +grid, 0.0f);
1497                         }
1498
1499                         if (show_axis_z) {
1500                                 UI_make_axis_color(col_grid, col_axis, 'Z');
1501                                 immAttrib3ubv(color, col_axis);
1502                                 immVertex3f(pos, 0.0f, 0.0f, -grid);
1503                                 immVertex3f(pos, 0.0f, 0.0f, +grid);
1504                         }
1505
1506                         immEnd();
1507                         immUnbindProgram();
1508                 }
1509
1510                 if (!write_depth)
1511                         glDepthMask(GL_TRUE);
1512         }
1513 }
1514
1515 /** could move this elsewhere, but tied into #ED_view3d_grid_scale */
1516 float ED_scene_grid_scale(Scene *scene, const char **grid_unit)
1517 {
1518         /* apply units */
1519         if (scene->unit.system) {
1520                 const void *usys;
1521                 int len;
1522
1523                 bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
1524
1525                 if (usys) {
1526                         int i = bUnit_GetBaseUnit(usys);
1527                         if (grid_unit)
1528                                 *grid_unit = bUnit_GetNameDisplay(usys, i);
1529                         return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length;
1530                 }
1531         }
1532
1533         return 1.0f;
1534 }
1535
1536 float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
1537 {
1538         return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
1539 }
1540
1541
1542 static void view3d_draw_grid(const bContext *C, ARegion *ar)
1543 {
1544         /* TODO viewport
1545          * Missing is the flags to check whether to draw it
1546          * for now now we are using the flags in v3d itself.
1547          *
1548          * Also for now always assume depth is there, so we
1549          * draw on top of it.
1550          */
1551         /**
1552          * Calculate pixel-size factor once, is used for lamps and object centers.
1553          * Used by #ED_view3d_pixel_size and typically not accessed directly.
1554          *
1555          * \note #BKE_camera_params_compute_viewplane' also calculates a pixel-size value,
1556          * passed to #RE_SetPixelSize, in ortho mode this is compatible with this value,
1557          * but in perspective mode its offset by the near-clip.
1558          *
1559          * 'RegionView3D.pixsize' is used for viewport drawing, not rendering.
1560          */
1561         Scene *scene = CTX_data_scene(C);
1562         View3D *v3d = CTX_wm_view3d(C);
1563         RegionView3D *rv3d = ar->regiondata;
1564
1565         const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
1566         const char *grid_unit = NULL;
1567
1568         /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override
1569          * objects if done last
1570          * needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views.
1571          */
1572         rv3d->gridview = ED_view3d_grid_scale(scene, v3d, &grid_unit);
1573
1574         glEnable(GL_DEPTH_TEST);
1575         glDepthMask(GL_FALSE); /* read & test depth, but don't alter it. TODO: separate UI depth buffer */
1576
1577         if (!draw_floor) {
1578                 ED_region_pixelspace(ar);
1579                 *(&grid_unit) = NULL;  /* drawgrid need this to detect/affect smallest valid unit... */
1580                 drawgrid(&scene->unit, ar, v3d, &grid_unit);
1581
1582                 gpuLoadProjectionMatrix(rv3d->winmat);
1583                 gpuLoadMatrix(rv3d->viewmat);
1584         }
1585         else {
1586                 drawfloor(scene, v3d, &grid_unit, false);
1587         }
1588
1589         glDisable(GL_DEPTH_TEST);
1590 }
1591
1592 static bool is_cursor_visible(Scene *scene, SceneLayer *sl)
1593 {
1594         Object *ob = OBACT_NEW;
1595
1596         /* don't draw cursor in paint modes, but with a few exceptions */
1597         if (ob && ob->mode & OB_MODE_ALL_PAINT) {
1598                 /* exception: object is in weight paint and has deforming armature in pose mode */
1599                 if (ob->mode & OB_MODE_WEIGHT_PAINT) {
1600                         if (BKE_object_pose_armature_get(ob) != NULL) {
1601                                 return true;
1602                         }
1603                 }
1604                 /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */
1605                 else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
1606                         const Paint *p = BKE_paint_get_active(scene, sl);
1607
1608                         if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) {
1609                                 if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) {
1610                                         return true;
1611                                 }
1612                         }
1613                 }
1614
1615                 /* no exception met? then don't draw cursor! */
1616                 return false;
1617         }
1618
1619         return true;
1620 }
1621
1622 static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
1623 {
1624         int co[2];
1625
1626         /* we don't want the clipping for cursor */
1627         if (ED_view3d_project_int_global(ar, ED_view3d_cursor3d_get(scene, v3d), co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
1628                 const float f5 = 0.25f * U.widget_unit;
1629                 const float f10 = 0.5f * U.widget_unit;
1630                 const float f20 = U.widget_unit;
1631                 
1632                 glLineWidth(1.0f);
1633
1634                 VertexFormat *format = immVertexFormat();
1635                 unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
1636                 unsigned int color = VertexFormat_add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
1637
1638                 immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
1639
1640                 const int segments = 16;
1641
1642                 immBegin(PRIM_LINE_LOOP, segments);
1643
1644                 for (int i = 0; i < segments; ++i) {
1645                         float angle = 2 * M_PI * ((float)i / (float)segments);
1646                         float x = co[0] + f10 * cosf(angle);
1647                         float y = co[1] + f10 * sinf(angle);
1648
1649                         if (i % 2 == 0)
1650                                 immAttrib3ub(color, 255, 0, 0);
1651                         else
1652                                 immAttrib3ub(color, 255, 255, 255);
1653
1654                         immVertex2f(pos, x, y);
1655                 }
1656                 immEnd();
1657
1658                 immUnbindProgram();
1659
1660                 VertexFormat_clear(format);
1661                 pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
1662
1663                 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1664
1665                 unsigned char crosshair_color[3];
1666                 UI_GetThemeColor3ubv(TH_VIEW_OVERLAY, crosshair_color);
1667                 immUniformColor3ubv(crosshair_color);
1668
1669                 immBegin(PRIM_LINES, 8);
1670                 immVertex2f(pos, co[0] - f20, co[1]);
1671                 immVertex2f(pos, co[0] - f5, co[1]);
1672                 immVertex2f(pos, co[0] + f5, co[1]);
1673                 immVertex2f(pos, co[0] + f20, co[1]);
1674                 immVertex2f(pos, co[0], co[1] - f20);
1675                 immVertex2f(pos, co[0], co[1] - f5);
1676                 immVertex2f(pos, co[0], co[1] + f5);
1677                 immVertex2f(pos, co[0], co[1] + f20);
1678                 immEnd();
1679
1680                 immUnbindProgram();
1681         }
1682 }
1683
1684 static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
1685 {
1686         const float k = U.rvisize * U.pixelsize;  /* axis size */
1687         const int bright = - 20 * (10 - U.rvibright);  /* axis alpha offset (rvibright has range 0-10) */
1688
1689         const float startx = rect->xmin + k + 1.0f;  /* axis center in screen coordinates, x=y */
1690         const float starty = rect->ymin + k + 1.0f;
1691
1692         float axis_pos[3][2];
1693         unsigned char axis_col[3][4];
1694
1695         int axis_order[3] = {0, 1, 2};
1696         axis_sort_v3(rv3d->viewinv[2], axis_order);
1697
1698         for (int axis_i = 0; axis_i < 3; axis_i++) {
1699                 int i = axis_order[axis_i];
1700
1701                 /* get position of each axis tip on screen */
1702                 float vec[3] = { 0.0f };
1703                 vec[i] = 1.0f;
1704                 mul_qt_v3(rv3d->viewquat, vec);
1705                 axis_pos[i][0] = startx + vec[0] * k;
1706                 axis_pos[i][1] = starty + vec[1] * k;
1707
1708                 /* get color of each axis */
1709                 UI_GetThemeColorShade3ubv(TH_AXIS_X + i, bright, axis_col[i]); /* rgb */
1710                 axis_col[i][3] = 255 * hypotf(vec[0], vec[1]); /* alpha */
1711         }
1712
1713         /* draw axis lines */
1714         glLineWidth(2.0f);
1715         glEnable(GL_LINE_SMOOTH);
1716         glEnable(GL_BLEND);
1717         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1718
1719         VertexFormat *format = immVertexFormat();
1720         unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
1721         unsigned int col = VertexFormat_add_attrib(format, "color", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT);
1722
1723         immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
1724         immBegin(PRIM_LINES, 6);
1725
1726         for (int axis_i = 0; axis_i < 3; axis_i++) {
1727                 int i = axis_order[axis_i];
1728
1729                 immAttrib4ubv(col, axis_col[i]);
1730                 immVertex2f(pos, startx, starty);
1731                 immVertex2fv(pos, axis_pos[i]);
1732         }
1733
1734         immEnd();
1735         immUnbindProgram();
1736         glDisable(GL_LINE_SMOOTH);
1737
1738         /* draw axis names */
1739         for (int axis_i = 0; axis_i < 3; axis_i++) {
1740                 int i = axis_order[axis_i];
1741
1742                 const char axis_text[2] = {'x' + i, '\0'};
1743                 BLF_color4ubv(BLF_default(), axis_col[i]);
1744                 BLF_draw_default_ascii(axis_pos[i][0] + 2, axis_pos[i][1] + 2, 0.0f, axis_text, 1);
1745         }
1746 }
1747
1748 #ifdef WITH_INPUT_NDOF
1749 /* draw center and axis of rotation for ongoing 3D mouse navigation */
1750 static void draw_rotation_guide(RegionView3D *rv3d)
1751 {
1752         float o[3];    /* center of rotation */
1753         float end[3];  /* endpoints for drawing */
1754
1755         GLubyte color[4] = {0, 108, 255, 255};  /* bright blue so it matches device LEDs */
1756
1757         negate_v3_v3(o, rv3d->ofs);
1758
1759         glEnable(GL_BLEND);
1760         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1761         glDepthMask(GL_FALSE);  /* don't overwrite zbuf */
1762
1763         VertexFormat *format = immVertexFormat();
1764         unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT);
1765         unsigned int col = VertexFormat_add_attrib(format, "color", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT);
1766
1767         immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
1768
1769         if (rv3d->rot_angle != 0.0f) {
1770                 /* -- draw rotation axis -- */
1771                 float scaled_axis[3];
1772                 const float scale = rv3d->dist;
1773                 mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale);
1774
1775
1776                 immBegin(PRIM_LINE_STRIP, 3);
1777                 color[3] = 0; /* more transparent toward the ends */
1778                 immAttrib4ubv(col, color);
1779                 add_v3_v3v3(end, o, scaled_axis);
1780                 immVertex3fv(pos, end);
1781
1782 #if 0
1783                 color[3] = 0.2f + fabsf(rv3d->rot_angle);  /* modulate opacity with angle */
1784                 /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */
1785 #endif
1786
1787                 color[3] = 127; /* more opaque toward the center */
1788                 immAttrib4ubv(col, color);
1789                 immVertex3fv(pos, o);
1790
1791                 color[3] = 0;
1792                 immAttrib4ubv(col, color);
1793                 sub_v3_v3v3(end, o, scaled_axis);
1794                 immVertex3fv(pos, end);
1795                 immEnd();
1796                 
1797                 /* -- draw ring around rotation center -- */
1798                 {
1799 #define     ROT_AXIS_DETAIL 13
1800
1801                         const float s = 0.05f * scale;
1802                         const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL);
1803
1804                         float q[4];  /* rotate ring so it's perpendicular to axis */
1805                         const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f;
1806                         if (!upright) {
1807                                 const float up[3] = {0.0f, 0.0f, 1.0f};
1808                                 float vis_angle, vis_axis[3];
1809
1810                                 cross_v3_v3v3(vis_axis, up, rv3d->rot_axis);
1811                                 vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis));
1812                                 axis_angle_to_quat(q, vis_axis, vis_angle);
1813                         }
1814
1815                         immBegin(PRIM_LINE_LOOP, ROT_AXIS_DETAIL);
1816                         color[3] = 63; /* somewhat faint */
1817                         immAttrib4ubv(col, color);
1818                         float angle = 0.0f;
1819                         for (int i = 0; i < ROT_AXIS_DETAIL; ++i, angle += step) {
1820                                 float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f};
1821
1822                                 if (!upright) {
1823                                         mul_qt_v3(q, p);
1824                                 }
1825
1826                                 add_v3_v3(p, o);
1827                                 immVertex3fv(pos, p);
1828                         }
1829                         immEnd();
1830
1831 #undef      ROT_AXIS_DETAIL
1832                 }
1833
1834                 color[3] = 255;  /* solid dot */
1835         }
1836         else
1837                 color[3] = 127;  /* see-through dot */
1838
1839         immUnbindProgram();
1840
1841         /* -- draw rotation center -- */
1842         immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
1843         glPointSize(5.0f);
1844         immBegin(PRIM_POINTS, 1);
1845         immAttrib4ubv(col, color);
1846         immVertex3fv(pos, o);
1847         immEnd();
1848         immUnbindProgram();
1849
1850 #if 0
1851         /* find screen coordinates for rotation center, then draw pretty icon */
1852         mul_m4_v3(rv3d->persinv, rot_center);
1853         UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN);
1854         /* ^^ just playing around, does not work */
1855 #endif
1856
1857         glDisable(GL_BLEND);
1858         glDepthMask(GL_TRUE);
1859 }
1860 #endif /* WITH_INPUT_NDOF */
1861
1862 /* ******************** non-meshes ***************** */
1863
1864 static void view3d_draw_non_mesh(
1865 Scene *scene, SceneLayer *sl, Object *ob, Base *base, View3D *v3d,
1866 RegionView3D *rv3d, const bool is_boundingbox, const unsigned char color[4])
1867 {
1868         gpuPushMatrix(); /* necessary? --merwin */
1869
1870         /* multiply view with object matrix.
1871          * local viewmat and persmat, to calculate projections */
1872         ED_view3d_init_mats_rv3d_gl(ob, rv3d);
1873
1874         switch (ob->type) {
1875                 case OB_MESH:
1876                 case OB_FONT:
1877                 case OB_CURVE:
1878                 case OB_SURF:
1879                 case OB_MBALL:
1880                         if (is_boundingbox) {
1881                                 draw_bounding_volume(ob, ob->boundtype, color);
1882                         }
1883                         break;
1884                 case OB_EMPTY:
1885                         drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, color);
1886                         break;
1887                 case OB_LAMP:
1888                         drawlamp(v3d, rv3d, base, OB_SOLID, DRAW_CONSTCOLOR, color, ob == OBACT_NEW);
1889                         break;
1890                 case OB_CAMERA:
1891                         drawcamera(scene, v3d, rv3d, base, DRAW_CONSTCOLOR, color);
1892                         break;
1893                 case OB_SPEAKER:
1894                         drawspeaker(color);
1895                         break;
1896                 case OB_LATTICE:
1897                         /* TODO */
1898                         break;
1899                 case OB_ARMATURE:
1900                         /* TODO */
1901                         break;
1902                 default:
1903                 /* TODO Viewport: handle the other cases*/
1904                         break;
1905         }
1906
1907         if (ob->rigidbody_object) {
1908                 draw_rigidbody_shape(ob, color);
1909         }
1910
1911         ED_view3d_clear_mats_rv3d(rv3d); /* no effect in release builds */
1912
1913         gpuPopMatrix(); /* see above */
1914 }
1915
1916 /* ******************** info ***************** */
1917
1918 /**
1919 * Render and camera border
1920 */
1921 static void view3d_draw_border(const bContext *C, ARegion *ar)
1922 {
1923         Scene *scene = CTX_data_scene(C);
1924         RegionView3D *rv3d = ar->regiondata;
1925         View3D *v3d = CTX_wm_view3d(C);
1926
1927         if (rv3d->persp == RV3D_CAMOB) {
1928                 drawviewborder(scene, ar, v3d);
1929         }
1930         else if (v3d->flag2 & V3D_RENDER_BORDER) {
1931                 drawrenderborder(ar, v3d);
1932         }
1933 }
1934
1935 /**
1936 * Grease Pencil
1937 */
1938 static void view3d_draw_grease_pencil(const bContext *UNUSED(C))
1939 {
1940         /* TODO viewport */
1941 }
1942
1943
1944 /**
1945 * Viewport Name
1946 */
1947 static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
1948 {
1949         const char *name = NULL;
1950
1951         switch (rv3d->view) {
1952                 case RV3D_VIEW_FRONT:
1953                         if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho");
1954                         else name = IFACE_("Front Persp");
1955                         break;
1956                 case RV3D_VIEW_BACK:
1957                         if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho");
1958                         else name = IFACE_("Back Persp");
1959                         break;
1960                 case RV3D_VIEW_TOP:
1961                         if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Top Ortho");
1962                         else name = IFACE_("Top Persp");
1963                         break;
1964                 case RV3D_VIEW_BOTTOM:
1965                         if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Bottom Ortho");
1966                         else name = IFACE_("Bottom Persp");
1967                         break;
1968                 case RV3D_VIEW_RIGHT:
1969                         if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Right Ortho");
1970                         else name = IFACE_("Right Persp");
1971                         break;
1972                 case RV3D_VIEW_LEFT:
1973                         if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Left Ortho");
1974                         else name = IFACE_("Left Persp");
1975                         break;
1976
1977                 default:
1978                         if (rv3d->persp == RV3D_CAMOB) {
1979                                 if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
1980                                         Camera *cam;
1981                                         cam = v3d->camera->data;
1982                                         if (cam->type == CAM_PERSP) {
1983                                                 name = IFACE_("Camera Persp");
1984                                         }
1985                                         else if (cam->type == CAM_ORTHO) {
1986                                                 name = IFACE_("Camera Ortho");
1987                                         }
1988                                         else {
1989                                                 BLI_assert(cam->type == CAM_PANO);
1990                                                 name = IFACE_("Camera Pano");
1991                                         }
1992                                 }
1993                                 else {
1994                                         name = IFACE_("Object as Camera");
1995                                 }
1996                         }
1997                         else {
1998                                 name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp");
1999                         }
2000         }
2001
2002         return name;
2003 }
2004
2005 static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
2006 {
2007         RegionView3D *rv3d = ar->regiondata;
2008         const char *name = view3d_get_name(v3d, rv3d);
2009         /* increase size for unicode languages (Chinese in utf-8...) */
2010 #ifdef WITH_INTERNATIONAL
2011         char tmpstr[96];
2012 #else
2013         char tmpstr[32];
2014 #endif
2015
2016         if (v3d->localvd) {
2017                 BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name);
2018                 name = tmpstr;
2019         }
2020
2021         UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
2022 #ifdef WITH_INTERNATIONAL
2023         BLF_draw_default(U.widget_unit + rect->xmin,  rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
2024 #else
2025         BLF_draw_default_ascii(U.widget_unit + rect->xmin,  rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
2026 #endif
2027 }
2028
2029 /**
2030  * draw info beside axes in bottom left-corner:
2031  * framenum, object name, bone name (if available), marker name (if available)
2032  */
2033
2034 static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
2035 {
2036         const int cfra = CFRA;
2037         const char *msg_pin = " (Pinned)";
2038         const char *msg_sep = " : ";
2039
2040         const int font_id = BLF_default();
2041
2042         char info[300];
2043         char *s = info;
2044         short offset = 1.5f * UI_UNIT_X + rect->xmin;
2045
2046         s += sprintf(s, "(%d)", cfra);
2047
2048         /*
2049          * info can contain:
2050          * - a frame (7 + 2)
2051          * - 3 object names (MAX_NAME)
2052          * - 2 BREAD_CRUMB_SEPARATORs (6)
2053          * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room!
2054          * - a marker name (MAX_NAME + 3)
2055          */
2056
2057         /* get name of marker on current frame (if available) */
2058         const char *markern = BKE_scene_find_marker_name(scene, cfra);
2059
2060         /* check if there is an object */
2061         if (ob) {
2062                 *s++ = ' ';
2063                 s += BLI_strcpy_rlen(s, ob->id.name + 2);
2064
2065                 /* name(s) to display depends on type of object */
2066                 if (ob->type == OB_ARMATURE) {
2067                         bArmature *arm = ob->data;
2068
2069                         /* show name of active bone too (if possible) */
2070                         if (arm->edbo) {
2071                                 if (arm->act_edbone) {
2072                                         s += BLI_strcpy_rlen(s, msg_sep);
2073                                         s += BLI_strcpy_rlen(s, arm->act_edbone->name);
2074                                 }
2075                         }
2076                         else if (ob->mode & OB_MODE_POSE) {
2077                                 if (arm->act_bone) {
2078
2079                                         if (arm->act_bone->layer & arm->layer) {
2080                                                 s += BLI_strcpy_rlen(s, msg_sep);
2081                                                 s += BLI_strcpy_rlen(s, arm->act_bone->name);
2082                                         }
2083                                 }
2084                         }
2085                 }
2086                 else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
2087                         /* try to display active bone and active shapekey too (if they exist) */
2088
2089                         if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) {
2090                                 Object *armobj = BKE_object_pose_armature_get(ob);
2091                                 if (armobj  && armobj->mode & OB_MODE_POSE) {
2092                                         bArmature *arm = armobj->data;
2093                                         if (arm->act_bone) {
2094                                                 if (arm->act_bone->layer & arm->layer) {
2095                                                         s += BLI_strcpy_rlen(s, msg_sep);
2096                                                         s += BLI_strcpy_rlen(s, arm->act_bone->name);
2097                                                 }
2098                                         }
2099                                 }
2100                         }
2101
2102                         Key *key = BKE_key_from_object(ob);
2103                         if (key) {
2104                                 KeyBlock *kb = BLI_findlink(&key->block, ob->shapenr - 1);
2105                                 if (kb) {
2106                                         s += BLI_strcpy_rlen(s, msg_sep);
2107                                         s += BLI_strcpy_rlen(s, kb->name);
2108                                         if (ob->shapeflag & OB_SHAPE_LOCK) {
2109                                                 s += BLI_strcpy_rlen(s, IFACE_(msg_pin));
2110                                         }
2111                                 }
2112                         }
2113                 }
2114
2115                 /* color depends on whether there is a keyframe */
2116                 if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL))
2117                         UI_FontThemeColor(font_id, TH_TIME_KEYFRAME);
2118                 else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra))
2119                         UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
2120                 else
2121                         UI_FontThemeColor(font_id, TH_TEXT_HI);
2122         }
2123         else {
2124                 /* no object */
2125                 if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra))
2126                         UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
2127                 else
2128                         UI_FontThemeColor(font_id, TH_TEXT_HI);
2129         }
2130
2131         if (markern) {
2132                 s += sprintf(s, " <%s>", markern);
2133         }
2134
2135         if (U.uiflag & USER_SHOW_ROTVIEWICON)
2136                 offset = U.widget_unit + (U.rvisize * 2) + rect->xmin;
2137
2138         BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info));
2139 }
2140
2141 /* ******************** view loop ***************** */
2142
2143 static void draw_all_objects(const bContext *C, ARegion *ar, const bool only_depth, const bool use_depth)
2144 {
2145         Scene *scene = CTX_data_scene(C);
2146         SceneLayer *sl = CTX_data_scene_layer(C);
2147         View3D *v3d = CTX_wm_view3d(C);
2148
2149         if (only_depth)
2150                 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2151
2152         if (only_depth || use_depth) {
2153                 glEnable(GL_DEPTH_TEST);
2154                 glDepthFunc(GL_LESS);
2155                 glDepthMask(GL_TRUE);
2156                 v3d->zbuf = true;
2157         }
2158
2159         for (Base *base = sl->object_bases.first; base; base = base->next) {
2160                 if ((base->flag & BASE_VISIBLED) != 0) {
2161                         /* dupli drawing */
2162                         if (base->object->transflag & OB_DUPLI)
2163                                 draw_dupli_objects(scene, sl, ar, v3d, base);
2164
2165                         draw_object(scene, sl, ar, v3d, base, 0);
2166                 }
2167         }
2168
2169         if (only_depth)
2170                 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2171
2172         if (only_depth || use_depth) {
2173                 glDisable(GL_DEPTH_TEST);
2174                 v3d->zbuf = false;
2175         }
2176 }
2177
2178 /**
2179  * Draw only the scene depth buffer
2180  */
2181 static void draw_depth_buffer(const bContext *C, ARegion *ar)
2182 {
2183         draw_all_objects(C, ar, true, true);
2184 }
2185
2186 /**
2187  * Required if the shaders need it or external engines
2188  * (e.g., Cycles requires depth buffer handled separately).
2189  */
2190 static void view3d_draw_prerender_buffers(const bContext *C, ARegion *ar, DrawData *draw_data)
2191 {
2192         View3D *v3d = CTX_wm_view3d(C);
2193
2194         /* TODO viewport */
2195         if (draw_data->is_render && ((!draw_data->clip_border) || (v3d->drawtype <= OB_WIRE))) {
2196                 draw_depth_buffer(C, ar);
2197         }
2198 }
2199
2200 /**
2201  * Draw all the plates that will fill the RGBD buffer
2202  */
2203 static void view3d_draw_solid_plates(const bContext *C, ARegion *ar, DrawData *draw_data)
2204 {
2205         /* realtime plates */
2206         if ((!draw_data->is_render) || draw_data->clip_border) {
2207                 view3d_draw_render_solid_surfaces(C, ar, true);
2208                 view3d_draw_render_transparent_surfaces(C);
2209                 view3d_draw_post_draw(C);
2210         }
2211
2212         /* offline plates */
2213         if (draw_data->is_render) {
2214                 Scene *scene = CTX_data_scene(C);
2215                 View3D *v3d = CTX_wm_view3d(C);
2216
2217                 /* TODO: move this outside of solid plates, after solid & before other 3D elements */
2218                 view3d_draw_render_draw(C, scene, ar, v3d, draw_data->clip_border, &draw_data->border_rect);
2219         }
2220
2221 #if VIEW3D_DRAW_DEBUG
2222         view3d_draw_debug_post_solid(C, ar, draw_data);
2223 #endif
2224 }
2225
2226 /**
2227  * Wires, outline, ...
2228  */
2229 static void view3d_draw_geometry_overlay(const bContext *C)
2230 {
2231         view3d_draw_wire_plates(C);
2232         view3d_draw_outline_plates(C);
2233 }
2234
2235 /* drawing cameras, lamps, ... */
2236 static void view3d_draw_non_meshes(const bContext *C, ARegion *ar)
2237 {
2238         /* TODO viewport
2239          * for now we draw them all, in the near future
2240          * we filter them based on the plates/layers
2241          */
2242         Scene *scene = CTX_data_scene(C);
2243         SceneLayer *sl = CTX_data_scene_layer(C);
2244         View3D *v3d = CTX_wm_view3d(C);
2245         RegionView3D *rv3d = ar->regiondata;
2246
2247         bool is_boundingbox = ((v3d->drawtype == OB_BOUNDBOX) ||
2248                                 ((v3d->drawtype == OB_RENDER) && (v3d->prev_drawtype == OB_BOUNDBOX)));
2249
2250         glEnable(GL_DEPTH_TEST);
2251         /* TODO Viewport
2252          * we are already temporarily writing to zbuffer in draw_object()
2253          * for now let's avoid writing again to zbuffer to prevent glitches
2254          */
2255
2256         for (Base *base = sl->object_bases.first; base; base = base->next) {
2257                 if ((base->flag & BASE_VISIBLED) != 0) {
2258                         Object *ob = base->object;
2259
2260                         unsigned char ob_wire_col[4];
2261                         draw_object_wire_color(scene, sl, base, ob_wire_col);
2262                         view3d_draw_non_mesh(scene, sl, ob, base, v3d, rv3d, is_boundingbox, ob_wire_col);
2263                 }
2264         }
2265
2266         glDisable(GL_DEPTH_TEST);
2267 }
2268
2269 /**
2270 * Parent lines, grid, ...
2271 */
2272 static void view3d_draw_other_elements(const bContext *C, ARegion *ar)
2273 {
2274         view3d_draw_grid(C, ar);
2275
2276 #ifdef WITH_INPUT_NDOF
2277         RegionView3D *rv3d = ar->regiondata;
2278
2279         if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((rv3d->viewlock & RV3D_LOCKED) == 0) && (rv3d->persp != RV3D_CAMOB))
2280                 /* TODO: draw something else (but not this) during fly mode */
2281                 draw_rotation_guide(rv3d);
2282 #endif
2283 }
2284
2285 /**
2286  * Paint brushes, armatures, ...
2287  */
2288 static void view3d_draw_tool_ui(const bContext *UNUSED(C))
2289 {
2290         /* TODO viewport */
2291 }
2292
2293 /**
2294  * Blueprint images
2295  */
2296 static void view3d_draw_reference_images(const bContext *UNUSED(C))
2297 {
2298         /* TODO viewport */
2299 }
2300
2301 /**
2302 * 3D manipulators
2303  */
2304 static void view3d_draw_manipulators(const bContext *C, const ARegion *ar)
2305 {
2306         View3D *v3d = CTX_wm_view3d(C);
2307         v3d->zbuf = false;
2308
2309         /* TODO, only draws 3D manipulators right now, need to see how 2D drawing will work in new viewport */
2310
2311         /* draw depth culled manipulators - manipulators need to be updated *after* view matrix was set up */
2312         /* TODO depth culling manipulators is not yet supported, just drawing _3D here, should
2313          * later become _IN_SCENE (and draw _3D separate) */
2314         WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_3D);
2315 }
2316
2317 /**
2318 * Information drawn on top of the solid plates and composed data
2319 */
2320 void view3d_draw_region_info(const bContext *C, ARegion *ar, const int offset)
2321 {
2322         RegionView3D *rv3d = ar->regiondata;
2323         View3D *v3d = CTX_wm_view3d(C);
2324         Scene *scene = CTX_data_scene(C);
2325         wmWindowManager *wm = CTX_wm_manager(C);
2326
2327         /* correct projection matrix */
2328         ED_region_pixelspace(ar);
2329
2330         /* local coordinate visible rect inside region, to accomodate overlapping ui */
2331         rcti rect;
2332         ED_region_visible_rect(ar, &rect);
2333
2334         /* Leave room for previously drawn info. */
2335         rect.ymax -= offset;
2336
2337         view3d_draw_border(C, ar);
2338         view3d_draw_grease_pencil(C);
2339
2340         if (U.uiflag & USER_SHOW_ROTVIEWICON) {
2341                 draw_view_axis(rv3d, &rect);
2342         }
2343
2344         if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
2345                 ED_scene_draw_fps(scene, &rect);
2346         }
2347         else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
2348                 draw_viewport_name(ar, v3d, &rect);
2349         }
2350
2351         if (U.uiflag & USER_DRAWVIEWINFO) {
2352                 SceneLayer *sl = CTX_data_scene_layer(C);
2353                 Object *ob = OBACT_NEW;
2354                 draw_selected_name(scene, ob, &rect);
2355         }
2356 #if 0 /* TODO */
2357         if (grid_unit) { /* draw below the viewport name */
2358                 char numstr[32] = "";
2359
2360                 UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
2361                 if (v3d->grid != 1.0f) {
2362                         BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
2363                 }
2364
2365                 BLF_draw_default_ascii(rect.xmin + U.widget_unit,
2366                                        rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f,
2367                                        numstr[0] ? numstr : grid_unit, sizeof(numstr));
2368         }
2369 #endif
2370 }
2371
2372 /**
2373  * This could run once per view, or even in parallel
2374  * for each of them. What is a "view"?
2375  * - a viewport with the camera elsewhere
2376  * - left/right stereo
2377  * - panorama / fisheye individual cubemap faces
2378  */
2379 static void view3d_draw_view(const bContext *C, ARegion *ar, DrawData *draw_data)
2380 {
2381         /* TODO - Technically this should be drawn to a few FBO, so we can handle
2382          * compositing better, but for now this will get the ball rolling (dfelinto) */
2383
2384         glDepthMask(GL_TRUE); /* should be set by default */
2385         glClear(GL_DEPTH_BUFFER_BIT);
2386 //      glDisable(GL_DEPTH_TEST); /* should be set by default */
2387
2388         view3d_draw_background(C); /* clears/overwrites entire color buffer */
2389
2390         ED_view3d_draw_setup_view(CTX_wm_window(C), CTX_data_scene(C), ar, CTX_wm_view3d(C), NULL, NULL);
2391
2392         glEnable(GL_DEPTH_TEST);
2393         glDepthFunc(GL_LEQUAL);
2394         view3d_draw_prerender_buffers(C, ar, draw_data); /* depth pre-pass */
2395
2396 //      glDepthFunc(GL_EQUAL); /* TODO: do this after separating surfaces from wires */
2397 //      glDepthMask(GL_FALSE); /* same TODO as above */
2398         view3d_draw_solid_plates(C, ar, draw_data);
2399
2400 //      glDepthFunc(GL_LEQUAL); /* same TODO as above */
2401 //      glDepthMask(GL_TRUE); /* same TODO as above */
2402
2403         view3d_draw_geometry_overlay(C);
2404         view3d_draw_non_meshes(C, ar);
2405         view3d_draw_other_elements(C, ar);
2406         view3d_draw_tool_ui(C);
2407         view3d_draw_reference_images(C);
2408         view3d_draw_manipulators(C, ar);
2409
2410         glDisable(GL_DEPTH_TEST);
2411
2412         view3d_draw_region_info(C, ar, 0);
2413
2414 #if VIEW3D_DRAW_DEBUG
2415         view3d_draw_debug(C, ar, draw_data);
2416 #endif
2417 }
2418
2419 static void view3d_draw_view_new(const bContext *C, ARegion *ar, DrawData *UNUSED(draw_data))
2420 {
2421         ED_view3d_draw_setup_view(CTX_wm_window(C), CTX_data_scene(C), ar, CTX_wm_view3d(C), NULL, NULL);
2422
2423         /* Only 100% compliant on new spec goes bellow */
2424         DRW_draw_view(C);
2425 }
2426
2427 void view3d_main_region_draw(const bContext *C, ARegion *ar)
2428 {
2429         Scene *scene = CTX_data_scene(C);
2430         View3D *v3d = CTX_wm_view3d(C);
2431         RegionView3D *rv3d = ar->regiondata;
2432         /* TODO layers - In the future we should get RE from Layers */
2433         RenderEngineType *type = RE_engines_find(scene->r.engine);
2434
2435         if (IS_VIEWPORT_LEGACY(v3d) && ((type->flag & RE_USE_LEGACY_PIPELINE) != 0)) {
2436                 view3d_main_region_draw_legacy(C, ar);
2437                 return;
2438         }
2439
2440         if (!rv3d->viewport)
2441                 rv3d->viewport = GPU_viewport_create();
2442
2443         /* TODO viewport - there is so much to be done, in fact a lot will need to happen in the space_view3d.c
2444          * before we even call the drawing routine, but let's move on for now (dfelinto)
2445          * but this is a provisory way to start seeing things in the viewport */
2446         DrawData draw_data;
2447         view3d_draw_data_init(C, ar, rv3d, &draw_data);
2448
2449         GPU_viewport_bind(rv3d->viewport, &ar->winrct);
2450
2451         if ((type->flag & RE_USE_LEGACY_PIPELINE) == 0) {
2452                 view3d_draw_view_new(C, ar, &draw_data);
2453         }
2454         else {
2455                 view3d_draw_view(C, ar, &draw_data);
2456         }
2457
2458         GPU_viewport_unbind(rv3d->viewport);
2459
2460         v3d->flag |= V3D_INVALID_BACKBUF;
2461 }
2462
2463
2464 /* -------------------------------------------------------------------- */
2465
2466 /** \name Offscreen Drawing
2467  * \{ */
2468
2469 static void view3d_stereo3d_setup_offscreen(
2470         Scene *scene, View3D *v3d, ARegion *ar,
2471         float winmat[4][4], const char *viewname)
2472 {
2473         /* update the viewport matrices with the new camera */
2474         if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
2475                 float viewmat[4][4];
2476                 const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
2477
2478                 BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
2479                 view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
2480         }
2481         else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
2482                 float viewmat[4][4];
2483                 Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
2484
2485                 BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
2486                 view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
2487         }
2488 }
2489
2490 void ED_view3d_draw_offscreen_init(Scene *scene, SceneLayer *sl, View3D *v3d)
2491 {
2492         RenderEngineType *type = RE_engines_find(scene->r.engine);
2493         if (IS_VIEWPORT_LEGACY(v3d) && ((type->flag & RE_USE_LEGACY_PIPELINE) != 0)) {
2494                 /* shadow buffers, before we setup matrices */
2495                 if (draw_glsl_material(scene, sl, NULL, v3d, v3d->drawtype)) {
2496                         VP_deprecated_gpu_update_lamps_shadows_world(scene, v3d);
2497                 }
2498         }
2499 }
2500
2501 /*
2502  * Function to clear the view
2503  */
2504 static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
2505 {
2506         glClear(GL_DEPTH_BUFFER_BIT);
2507
2508         if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) {
2509                 VP_view3d_draw_background_world(scene, v3d, ar->regiondata);
2510         }
2511         else {
2512                 VP_view3d_draw_background_none();
2513         }
2514 }
2515
2516 /* ED_view3d_draw_offscreen_init should be called before this to initialize
2517  * stuff like shadow buffers
2518  */
2519 void ED_view3d_draw_offscreen(
2520         Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy,
2521         float viewmat[4][4], float winmat[4][4],
2522         bool do_bgpic, bool do_sky, bool is_persp, const char *viewname,
2523         GPUFX *fx, GPUFXSettings *fx_settings,
2524         GPUOffScreen *ofs)
2525 {
2526         bool do_compositing = false;
2527         RegionView3D *rv3d = ar->regiondata;
2528
2529         /* set temporary new size */
2530         int bwinx = ar->winx;
2531         int bwiny = ar->winy;
2532         rcti brect = ar->winrct;
2533
2534         ar->winx = winx;
2535         ar->winy = winy;
2536         ar->winrct.xmin = 0;
2537         ar->winrct.ymin = 0;
2538         ar->winrct.xmax = winx;
2539         ar->winrct.ymax = winy;
2540
2541         struct bThemeState theme_state;
2542         UI_Theme_Store(&theme_state);
2543         UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
2544
2545         /* set flags */
2546         G.f |= G_RENDER_OGL;
2547
2548         if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
2549                 /* free images which can have changed on frame-change
2550                  * warning! can be slow so only free animated images - campbell */
2551                 GPU_free_images_anim();
2552         }
2553
2554         gpuPushProjectionMatrix();
2555         gpuLoadIdentity();
2556         gpuPushMatrix();
2557         gpuLoadIdentity();
2558
2559         /* clear opengl buffers */
2560         if (do_sky) {
2561                 view3d_main_region_clear(scene, v3d, ar);
2562         }
2563         else {
2564                 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
2565                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2566         }
2567
2568         if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
2569                 view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname);
2570         else
2571                 view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
2572
2573         /* main drawing call */
2574         RenderEngineType *type = RE_engines_find(scene->r.engine);
2575         if (IS_VIEWPORT_LEGACY(v3d) && ((type->flag & RE_USE_LEGACY_PIPELINE) != 0)) {
2576
2577                 /* framebuffer fx needed, we need to draw offscreen first */
2578                 if (v3d->fx_settings.fx_flag && fx) {
2579                         GPUSSAOSettings *ssao = NULL;
2580
2581                         if (v3d->drawtype < OB_SOLID) {
2582                                 ssao = v3d->fx_settings.ssao;
2583                                 v3d->fx_settings.ssao = NULL;
2584                         }
2585
2586                         do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings);
2587
2588                         if (ssao)
2589                                 v3d->fx_settings.ssao = ssao;
2590                 }
2591
2592                 VP_deprecated_view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL);
2593
2594                 /* post process */
2595                 if (do_compositing) {
2596                         if (!winmat)
2597                                 is_persp = rv3d->is_persp;
2598                         GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs);
2599                 }
2600
2601                 if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
2602                         /* draw grease-pencil stuff */
2603                         ED_region_pixelspace(ar);
2604
2605                         if (v3d->flag2 & V3D_SHOW_GPENCIL) {
2606                                 /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
2607                                 ED_gpencil_draw_view3d(NULL, scene, v3d, ar, false);
2608                         }
2609
2610                         /* freeing the images again here could be done after the operator runs, leaving for now */
2611                         GPU_free_images_anim();
2612                 }
2613         }
2614         else {
2615                 /* XXX, should take depsgraph as arg */
2616                 DRW_draw_render_loop_offscreen(scene->depsgraph, ar, v3d, ofs);
2617         }
2618
2619         /* restore size */
2620         ar->winx = bwinx;
2621         ar->winy = bwiny;
2622         ar->winrct = brect;
2623
2624         gpuPopProjectionMatrix();
2625         gpuPopMatrix();
2626
2627         UI_Theme_Restore(&theme_state);
2628
2629         G.f &= ~G_RENDER_OGL;
2630 }
2631
2632 /**
2633  * Utility func for ED_view3d_draw_offscreen
2634  *
2635  * \param ofs: Optional off-screen buffer, can be NULL.
2636  * (avoids re-creating when doing multiple GL renders).
2637  */
2638 ImBuf *ED_view3d_draw_offscreen_imbuf(
2639         Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, int sizex, int sizey,
2640         unsigned int flag, bool draw_background,
2641         int alpha_mode, int samples, bool full_samples, const char *viewname,
2642         /* output vars */
2643         GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
2644 {
2645         RegionView3D *rv3d = ar->regiondata;
2646         const bool draw_sky = (alpha_mode == R_ADDSKY);
2647
2648         /* view state */
2649         GPUFXSettings fx_settings = v3d->fx_settings;
2650         bool is_ortho = false;
2651         float winmat[4][4];
2652
2653         if (ofs && ((GPU_offscreen_width(ofs) != sizex) || (GPU_offscreen_height(ofs) != sizey))) {
2654                 /* sizes differ, can't reuse */
2655                 ofs = NULL;
2656         }
2657
2658         const bool own_ofs = (ofs == NULL);
2659
2660         if (own_ofs) {
2661                 /* bind */
2662                 ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, err_out);
2663                 if (ofs == NULL) {
2664                         return NULL;
2665                 }
2666         }
2667
2668         ED_view3d_draw_offscreen_init(scene, sl, v3d);
2669
2670         GPU_offscreen_bind(ofs, true);
2671
2672         /* read in pixels & stamp */
2673         ImBuf *ibuf = IMB_allocImBuf(sizex, sizey, 32, flag);
2674
2675         /* render 3d view */
2676         if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
2677                 CameraParams params;
2678                 Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
2679
2680                 BKE_camera_params_init(&params);
2681                 /* fallback for non camera objects */
2682                 params.clipsta = v3d->near;
2683                 params.clipend = v3d->far;
2684                 BKE_camera_params_from_object(&params, camera);
2685                 BKE_camera_multiview_params(&scene->r, &params, camera, viewname);
2686                 BKE_camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
2687                 BKE_camera_params_compute_matrix(&params);
2688
2689                 BKE_camera_to_gpu_dof(camera, &fx_settings);
2690
2691                 is_ortho = params.is_ortho;
2692                 copy_m4_m4(winmat, params.winmat);
2693         }
2694         else {
2695                 rctf viewplane;
2696                 float clipsta, clipend;
2697
2698                 is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
2699                 if (is_ortho) {
2700                         orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
2701                 }
2702                 else {
2703                         perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
2704                 }
2705         }
2706
2707         if ((samples && full_samples) == 0) {
2708                 /* Single-pass render, common case */
2709                 ED_view3d_draw_offscreen(
2710                         scene, v3d, ar, sizex, sizey, NULL, winmat,
2711                         draw_background, draw_sky, !is_ortho, viewname,
2712                         fx, &fx_settings, ofs);
2713
2714                 if (ibuf->rect_float) {
2715                         GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
2716                 }
2717                 else if (ibuf->rect) {
2718                         GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
2719                 }
2720         }
2721         else {
2722                 /* Multi-pass render, use accumulation buffer & jitter for 'full' oversampling.
2723                  * Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */
2724                 static float jit_ofs[32][2];
2725                 float winmat_jitter[4][4];
2726                 /* use imbuf as temp storage, before writing into it from accumulation buffer */
2727                 unsigned char *rect_temp = ibuf->rect ? (void *)ibuf->rect : (void *)ibuf->rect_float;
2728                 unsigned int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int[4]), "accum1");
2729
2730                 BLI_jitter_init(jit_ofs, samples);
2731
2732                 /* first sample buffer, also initializes 'rv3d->persmat' */
2733                 ED_view3d_draw_offscreen(
2734                         scene, v3d, ar, sizex, sizey, NULL, winmat,
2735                         draw_background, draw_sky, !is_ortho, viewname,
2736                         fx, &fx_settings, ofs);
2737                 GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
2738
2739                 unsigned i = sizex * sizey * 4;
2740                 while (i--) {
2741                         accum_buffer[i] = rect_temp[i];
2742                 }
2743
2744                 /* skip the first sample */
2745                 for (int j = 1; j < samples; j++) {
2746                         copy_m4_m4(winmat_jitter, winmat);
2747                         window_translate_m4(
2748                                 winmat_jitter, rv3d->persmat,
2749                                 (jit_ofs[j][0] * 2.0f) / sizex,
2750                                 (jit_ofs[j][1] * 2.0f) / sizey);
2751
2752                         ED_view3d_draw_offscreen(
2753                                 scene, v3d, ar, sizex, sizey, NULL, winmat_jitter,
2754                                 draw_background, draw_sky, !is_ortho, viewname,
2755                                 fx, &fx_settings, ofs);
2756                         GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
2757
2758                         i = sizex * sizey * 4;
2759                         while (i--) {
2760                                 accum_buffer[i] += rect_temp[i];
2761                         }
2762                 }
2763
2764                 if (ibuf->rect_float) {
2765                         float *rect_float = ibuf->rect_float;
2766                         i = sizex * sizey * 4;
2767                         while (i--) {
2768                                 rect_float[i] = (float)(accum_buffer[i] / samples) * (1.0f / 255.0f);
2769                         }
2770                 }
2771                 else {
2772                         unsigned char *rect_ub = (unsigned char *)ibuf->rect;
2773                         i = sizex * sizey * 4;
2774                         while (i--) {
2775                                 rect_ub[i] = accum_buffer[i] / samples;
2776                         }
2777                 }
2778
2779                 MEM_freeN(accum_buffer);
2780         }
2781
2782         /* unbind */
2783         GPU_offscreen_unbind(ofs, true);
2784
2785         if (own_ofs) {
2786                 GPU_offscreen_free(ofs);
2787         }
2788
2789         if (ibuf->rect_float && ibuf->rect)
2790                 IMB_rect_from_float(ibuf);
2791
2792         return ibuf;
2793 }
2794
2795 /**
2796  * Creates own fake 3d views (wrapping #ED_view3d_draw_offscreen_imbuf)
2797  *
2798  * \param ofs: Optional off-screen buffer can be NULL.
2799  * (avoids re-creating when doing multiple GL renders).
2800  *
2801  * \note used by the sequencer
2802  */
2803 ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
2804         Scene *scene, SceneLayer *sl, Object *camera, int width, int height,
2805         unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background,
2806         int alpha_mode, int samples, bool full_samples, const char *viewname,
2807         GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
2808 {
2809         View3D v3d = {NULL};
2810         ARegion ar = {NULL};
2811         RegionView3D rv3d = {{{0}}};
2812
2813         /* connect data */
2814         v3d.regionbase.first = v3d.regionbase.last = &ar;
2815         ar.regiondata = &rv3d;
2816         ar.regiontype = RGN_TYPE_WINDOW;
2817
2818         v3d.camera = camera;
2819         v3d.lay = scene->lay;
2820         v3d.drawtype = drawtype;
2821         v3d.flag2 = V3D_RENDER_OVERRIDE;
2822
2823         if (use_gpencil)
2824                 v3d.flag2 |= V3D_SHOW_GPENCIL;
2825
2826         if (use_solid_tex)
2827                 v3d.flag2 |= V3D_SOLID_TEX;
2828
2829         if (draw_background)
2830                 v3d.flag3 |= V3D_SHOW_WORLD;
2831
2832         rv3d.persp = RV3D_CAMOB;
2833
2834         copy_m4_m4(rv3d.viewinv, v3d.camera->obmat);
2835         normalize_m4(rv3d.viewinv);
2836         invert_m4_m4(rv3d.viewmat, rv3d.viewinv);
2837
2838         {
2839                 CameraParams params;
2840                 Object *view_camera = BKE_camera_multiview_render(scene, v3d.camera, viewname);
2841
2842                 BKE_camera_params_init(&params);
2843                 BKE_camera_params_from_object(&params, view_camera);
2844                 BKE_camera_multiview_params(&scene->r, &params, view_camera, viewname);
2845                 BKE_camera_params_compute_viewplane(&params, width, height, scene->r.xasp, scene->r.yasp);
2846                 BKE_camera_params_compute_matrix(&params);
2847
2848                 copy_m4_m4(rv3d.winmat, params.winmat);
2849                 v3d.near = params.clipsta;
2850                 v3d.far = params.clipend;
2851                 v3d.lens = params.lens;
2852         }
2853
2854         mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
2855         invert_m4_m4(rv3d.persinv, rv3d.viewinv);
2856
2857         return ED_view3d_draw_offscreen_imbuf(
2858                 scene, sl, &v3d, &ar, width, height, flag,
2859                 draw_background, alpha_mode, samples, full_samples, viewname,
2860                 fx, ofs, err_out);
2861 }
2862
2863 /** \} */
2864
2865
2866 /* -------------------------------------------------------------------- */
2867
2868 /** \name Legacy Interface
2869  *
2870  * This will be removed once the viewport gets replaced
2871  * meanwhile it should keep the old viewport working.
2872  *
2873  * \{ */
2874
2875 void VP_legacy_drawcursor(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d)
2876 {
2877         if (is_cursor_visible(scene, sl)) {
2878                 drawcursor(scene, ar, v3d);
2879         }
2880 }
2881
2882 void VP_legacy_draw_view_axis(RegionView3D *rv3d, rcti *rect)
2883 {
2884         draw_view_axis(rv3d, rect);
2885 }
2886
2887 void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
2888 {
2889         draw_viewport_name(ar, v3d, rect);
2890 }
2891
2892 void VP_legacy_draw_selected_name(Scene *scene, Object *ob, rcti *rect)
2893 {
2894         draw_selected_name(scene, ob, rect);
2895 }
2896
2897 void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
2898 {
2899         drawgrid(unit, ar, v3d, grid_unit);
2900 }
2901
2902 void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth)
2903 {
2904         drawfloor(scene, v3d, grid_unit, write_depth);
2905 }
2906
2907 void VP_legacy_view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
2908 {
2909         view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
2910 }
2911
2912 bool VP_legacy_view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d)
2913 {
2914         return view3d_stereo3d_active(CTX_wm_window(C), scene, v3d, rv3d);
2915 }
2916
2917 void VP_legacy_view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
2918 {
2919         view3d_stereo3d_setup(scene, v3d, ar);
2920 }
2921
2922 bool VP_legacy_use_depth(Scene *scene, View3D *v3d)
2923 {
2924         return use_depth_doit(scene, v3d);
2925 }
2926
2927 void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
2928 {
2929         drawviewborder(scene, ar, v3d);
2930 }
2931
2932 void VP_drawrenderborder(ARegion *ar, View3D *v3d)
2933 {
2934         drawrenderborder(ar, v3d);
2935 }
2936
2937 void VP_view3d_draw_background_none(void)
2938 {
2939         if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
2940                 view3d_draw_background_gradient();
2941         }
2942         else {
2943                 view3d_draw_background_none();
2944         }
2945 }
2946
2947 void VP_view3d_draw_background_world(Scene *scene, View3D *v3d, RegionView3D *rv3d)
2948 {
2949         view3d_draw_background_world(scene, v3d, rv3d);
2950 }
2951
2952 void VP_view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
2953 {
2954         view3d_main_region_clear(scene, v3d, ar);
2955 }
2956
2957 /** \} */