Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / space_view3d / drawmesh.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) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, full update, glsl support
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_view3d/drawmesh.c
27  *  \ingroup spview3d
28  */
29
30 #include <string.h>
31 #include <math.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "BLI_utildefines.h"
36 #include "BLI_bitmap.h"
37 #include "BLI_math.h"
38
39 #include "DNA_material_types.h"
40 #include "DNA_mesh_types.h"
41 #include "DNA_meshdata_types.h"
42 #include "DNA_node_types.h"
43 #include "DNA_object_types.h"
44 #include "DNA_property_types.h"
45 #include "DNA_scene_types.h"
46 #include "DNA_screen_types.h"
47 #include "DNA_view3d_types.h"
48
49 #include "BKE_DerivedMesh.h"
50 #include "BKE_global.h"
51 #include "BKE_image.h"
52 #include "BKE_material.h"
53 #include "BKE_paint.h"
54 #include "BKE_property.h"
55 #include "BKE_editmesh.h"
56 #include "BKE_scene.h"
57
58 #include "BIF_glutil.h"
59
60 #include "UI_resources.h"
61
62 #include "GPU_draw.h"
63 #include "GPU_material.h"
64 #include "GPU_basic_shader.h"
65 #include "GPU_shader.h"
66 #include "GPU_matrix.h"
67
68 #include "RE_engine.h"
69
70 #include "ED_uvedit.h"
71
72 #include "view3d_intern.h"  /* own include */
73
74 /* user data structures for derived mesh callbacks */
75 typedef struct drawMeshFaceSelect_userData {
76         Mesh *me;
77         BLI_bitmap *edge_flags; /* pairs of edge options (visible, select) */
78 } drawMeshFaceSelect_userData;
79
80 /**************************** Face Select Mode *******************************/
81
82 /* mainly to be less confusing */
83 BLI_INLINE int edge_vis_index(const int index) { return index * 2; }
84 BLI_INLINE int edge_sel_index(const int index) { return index * 2 + 1; }
85
86 static BLI_bitmap *get_tface_mesh_marked_edge_info(Mesh *me, bool draw_select_edges)
87 {
88         BLI_bitmap *bitmap_edge_flags = BLI_BITMAP_NEW(me->totedge * 2, __func__);
89         MPoly *mp;
90         MLoop *ml;
91         int i, j;
92         bool select_set;
93         
94         for (i = 0; i < me->totpoly; i++) {
95                 mp = &me->mpoly[i];
96
97                 if (!(mp->flag & ME_HIDE)) {
98                         select_set = (mp->flag & ME_FACE_SEL) != 0;
99
100                         ml = me->mloop + mp->loopstart;
101                         for (j = 0; j < mp->totloop; j++, ml++) {
102                                 if ((draw_select_edges == false) &&
103                                     (select_set && BLI_BITMAP_TEST(bitmap_edge_flags, edge_sel_index(ml->e))))
104                                 {
105                                         BLI_BITMAP_DISABLE(bitmap_edge_flags, edge_vis_index(ml->e));
106                                 }
107                                 else {
108                                         BLI_BITMAP_ENABLE(bitmap_edge_flags, edge_vis_index(ml->e));
109                                         if (select_set) {
110                                                 BLI_BITMAP_ENABLE(bitmap_edge_flags, edge_sel_index(ml->e));
111                                         }
112                                 }
113                         }
114                 }
115         }
116
117         return bitmap_edge_flags;
118 }
119
120
121 static DMDrawOption draw_mesh_face_select__setHiddenOpts(void *userData, int index)
122 {
123         drawMeshFaceSelect_userData *data = userData;
124         Mesh *me = data->me;
125
126         if (me->drawflag & ME_DRAWEDGES) {
127                 if ((BLI_BITMAP_TEST(data->edge_flags, edge_vis_index(index))))
128                         return DM_DRAW_OPTION_NORMAL;
129                 else
130                         return DM_DRAW_OPTION_SKIP;
131         }
132         else if (BLI_BITMAP_TEST(data->edge_flags, edge_sel_index(index)) &&
133                  BLI_BITMAP_TEST(data->edge_flags, edge_vis_index(index)))
134         {
135                 return DM_DRAW_OPTION_NORMAL;
136         }
137         else {
138                 return DM_DRAW_OPTION_SKIP;
139         }
140 }
141
142 static DMDrawOption draw_mesh_face_select__setSelectOpts(void *userData, int index)
143 {
144         drawMeshFaceSelect_userData *data = userData;
145         return (BLI_BITMAP_TEST(data->edge_flags, edge_sel_index(index)) &&
146                 BLI_BITMAP_TEST(data->edge_flags, edge_vis_index(index))) ? DM_DRAW_OPTION_NORMAL : DM_DRAW_OPTION_SKIP;
147 }
148
149 /* draws unselected */
150 static DMDrawOption draw_mesh_face_select__drawFaceOptsInv(void *userData, int index)
151 {
152         Mesh *me = (Mesh *)userData;
153
154         MPoly *mpoly = &me->mpoly[index];
155         if (!(mpoly->flag & ME_HIDE) && !(mpoly->flag & ME_FACE_SEL))
156                 return DM_DRAW_OPTION_NORMAL;
157         else
158                 return DM_DRAW_OPTION_SKIP;
159 }
160
161 void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm, bool draw_select_edges)
162 {
163         drawMeshFaceSelect_userData data;
164
165         data.me = me;
166         data.edge_flags = get_tface_mesh_marked_edge_info(me, draw_select_edges);
167
168         glEnable(GL_DEPTH_TEST);
169         ED_view3d_polygon_offset(rv3d, 1.0);
170
171         /* Draw (Hidden) Edges */
172         setlinestyle(1);
173         UI_ThemeColor(TH_EDGE_FACESEL);
174         dm->drawMappedEdges(dm, draw_mesh_face_select__setHiddenOpts, &data);
175         setlinestyle(0);
176
177         /* Draw Selected Faces */
178         if (me->drawflag & ME_DRAWFACES) {
179                 glEnable(GL_BLEND);
180                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
181                 /* dull unselected faces so as not to get in the way of seeing color */
182                 glColor4ub(96, 96, 96, 64);
183                 dm->drawMappedFaces(dm, draw_mesh_face_select__drawFaceOptsInv, NULL, NULL, (void *)me, DM_DRAW_SKIP_HIDDEN);
184                 glDisable(GL_BLEND);
185         }
186         
187         ED_view3d_polygon_offset(rv3d, 1.0);
188
189         /* Draw Stippled Outline for selected faces */
190         glColor3ub(255, 255, 255);
191         setlinestyle(1);
192         dm->drawMappedEdges(dm, draw_mesh_face_select__setSelectOpts, &data);
193         setlinestyle(0);
194
195         ED_view3d_polygon_offset(rv3d, 0.0);  /* resets correctly now, even after calling accumulated offsets */
196
197         MEM_freeN(data.edge_flags);
198 }
199
200 /***************************** Texture Drawing ******************************/
201
202 /* when face select is on, use face hidden flag */
203 static DMDrawOption wpaint__setSolidDrawOptions_facemask(void *userData, int index)
204 {
205         Mesh *me = (Mesh *)userData;
206         MPoly *mp = &me->mpoly[index];
207         if (mp->flag & ME_HIDE)
208                 return DM_DRAW_OPTION_SKIP;
209         return DM_DRAW_OPTION_NORMAL;
210 }
211
212 /************************** NEW SHADING NODES ********************************/
213
214 typedef struct TexMatCallback {
215         Scene *scene;
216         Object *ob;
217         Mesh *me;
218         DerivedMesh *dm;
219         bool shadeless;
220         bool two_sided_lighting;
221 } TexMatCallback;
222
223 void draw_mesh_textured(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d,
224                         Object *ob, DerivedMesh *dm, const int draw_flags)
225 {
226         UNUSED_VARS(scene, sl, v3d, rv3d, ob, dm, draw_flags);
227         return;
228 }
229
230 /* Vertex Paint and Weight Paint */
231 static void draw_mesh_paint_light_begin(void)
232 {
233         /* get material diffuse color from vertex colors but set default spec */
234         const float specular[3] = {0.47f, 0.47f, 0.47f};
235         GPU_basic_shader_colors(NULL, specular, 35, 1.0f);
236         GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
237 }
238
239 static void draw_mesh_paint_light_end(void)
240 {
241         GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
242 }
243
244 void draw_mesh_paint_weight_faces(DerivedMesh *dm, const bool use_light,
245                                   void *facemask_cb, void *user_data)
246 {
247         DMSetMaterial setMaterial = GPU_object_materials_check() ? GPU_object_material_bind : NULL;
248         int flags = DM_DRAW_USE_COLORS;
249
250         if (use_light) {
251                 draw_mesh_paint_light_begin();
252                 flags |= DM_DRAW_NEED_NORMALS;
253         }
254
255         dm->drawMappedFaces(dm, (DMSetDrawOptions)facemask_cb, setMaterial, NULL, user_data, flags);
256
257         if (use_light) {
258                 draw_mesh_paint_light_end();
259         }
260 }
261
262 void draw_mesh_paint_vcolor_faces(DerivedMesh *dm, const bool use_light,
263                                   void *facemask_cb, void *user_data,
264                                   const Mesh *me)
265 {
266         DMSetMaterial setMaterial = GPU_object_materials_check() ? GPU_object_material_bind : NULL;
267         int flags = 0;
268
269         if (use_light) {
270                 draw_mesh_paint_light_begin();
271                 flags |= DM_DRAW_NEED_NORMALS;
272         }
273
274         if (me->mloopcol) {
275                 dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data,
276                                     DM_DRAW_USE_COLORS | flags);
277         }
278         else {
279                 glColor3f(1.0f, 1.0f, 1.0f);
280                 dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data, flags);
281         }
282
283         if (use_light) {
284                 draw_mesh_paint_light_end();
285         }
286 }
287
288 void draw_mesh_paint_weight_edges(RegionView3D *rv3d, DerivedMesh *dm,
289                                   const bool use_depth, const bool use_alpha,
290                                   void *edgemask_cb, void *user_data)
291 {
292         /* weight paint in solid mode, special case. focus on making the weights clear
293          * rather than the shading, this is also forced in wire view */
294
295         if (use_depth) {
296                 ED_view3d_polygon_offset(rv3d, 1.0);
297                 glDepthMask(0);  /* disable write in zbuffer, selected edge wires show better */
298         }
299         else {
300                 glDisable(GL_DEPTH_TEST);
301         }
302
303         if (use_alpha) {
304                 glEnable(GL_BLEND);
305         }
306
307         glColor4ub(255, 255, 255, 96);
308         GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
309         GPU_basic_shader_line_stipple(1, 0xAAAA);
310
311         dm->drawMappedEdges(dm, (DMSetDrawOptions)edgemask_cb, user_data);
312
313         if (use_depth) {
314                 ED_view3d_polygon_offset(rv3d, 0.0);
315                 glDepthMask(1);
316         }
317         else {
318                 glEnable(GL_DEPTH_TEST);
319         }
320
321         GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
322
323         if (use_alpha) {
324                 glDisable(GL_BLEND);
325         }
326 }
327
328 void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
329                      Object *ob, DerivedMesh *dm, const int draw_flags)
330 {
331         DMSetDrawOptions facemask = NULL;
332         Mesh *me = ob->data;
333         const bool use_light = (v3d->drawtype >= OB_SOLID);
334
335         /* hide faces in face select mode */
336         if (me->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL))
337                 facemask = wpaint__setSolidDrawOptions_facemask;
338
339         if (ob->mode & OB_MODE_WEIGHT_PAINT) {
340                 draw_mesh_paint_weight_faces(dm, use_light, facemask, me);
341         }
342         else if (ob->mode & OB_MODE_VERTEX_PAINT) {
343                 draw_mesh_paint_vcolor_faces(dm, use_light, facemask, me, me);
344         }
345
346         /* draw face selection on top */
347         if (draw_flags & DRAW_FACE_SELECT) {
348                 bool draw_select_edges = (ob->mode & OB_MODE_TEXTURE_PAINT) == 0;
349                 draw_mesh_face_select(rv3d, me, dm, draw_select_edges);
350         }
351         else if ((use_light == false) || (ob->dtx & OB_DRAWWIRE)) {
352                 const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) || !(ob->mode & OB_MODE_WEIGHT_PAINT);
353                 const bool use_alpha = (ob->mode & OB_MODE_VERTEX_PAINT) == 0;
354
355                 if (use_alpha == false) {
356                         set_inverted_drawing(1);
357                 }
358
359                 draw_mesh_paint_weight_edges(rv3d, dm, use_depth, use_alpha, NULL, NULL);
360
361                 if (use_alpha == false) {
362                         set_inverted_drawing(0);
363                 }
364         }
365 }
366