Mesh drawing optimization and fixes:
[blender-staging.git] / source / blender / blenkernel / intern / editderivedmesh.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) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/editderivedmesh.c
29  *  \ingroup bke
30  */
31
32 #include "GL/glew.h"
33
34 #include "BLI_utildefines.h"
35 #include "BLI_blenlib.h"
36 #include "BLI_edgehash.h"
37 #include "BLI_editVert.h"
38 #include "BLI_math.h"
39 #include "BLI_pbvh.h"
40
41 #include "BKE_cdderivedmesh.h"
42 #include "BKE_global.h"
43 #include "BKE_mesh.h"
44 #include "BKE_paint.h"
45
46
47 #include "DNA_meshdata_types.h"
48 #include "DNA_object_types.h"
49 #include "DNA_curve_types.h" /* for Curve */
50
51 #include "MEM_guardedalloc.h"
52
53 #include "GPU_buffers.h"
54 #include "GPU_draw.h"
55 #include "GPU_extensions.h"
56 #include "GPU_material.h"
57
58 #include <string.h>
59 #include <limits.h>
60 #include <math.h>
61
62 extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
63
64 static void emDM_foreachMappedVert(
65                 DerivedMesh *dm,
66                 void (*func)(void *userData, int index, float *co, float *no_f, short *no_s),
67                 void *userData)
68 {
69         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
70         EditVert *eve;
71         int i;
72
73         for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
74                 if (emdm->vertexCos) {
75                         func(userData, i, emdm->vertexCos[i], emdm->vertexNos[i], NULL);
76                 }
77                 else {
78                         func(userData, i, eve->co, eve->no, NULL);
79                 }
80         }
81 }
82 static void emDM_foreachMappedEdge(
83                 DerivedMesh *dm,
84                 void (*func)(void *userData, int index, float *v0co, float *v1co),
85                 void *userData)
86 {
87         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
88         EditEdge *eed;
89         int i;
90
91         if (emdm->vertexCos) {
92                 EditVert *eve;
93
94                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
95                         eve->tmp.l = (intptr_t) i++;
96                 for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next)
97                         func(userData, i, emdm->vertexCos[(int) eed->v1->tmp.l], emdm->vertexCos[(int) eed->v2->tmp.l]);
98         }
99         else {
100                 for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next)
101                         func(userData, i, eed->v1->co, eed->v2->co);
102         }
103 }
104
105 static void emDM_drawMappedEdges(
106                 DerivedMesh *dm,
107                 int (*setDrawOptions)(void *userData, int index),
108                 void *userData)
109 {
110         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
111         EditEdge *eed;
112         int i;
113
114         if (emdm->vertexCos) {
115                 EditVert *eve;
116
117                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
118                         eve->tmp.l = (intptr_t) i++;
119
120                 glBegin(GL_LINES);
121                 for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
122                         if (!setDrawOptions || setDrawOptions(userData, i)) {
123                                 glVertex3fv(emdm->vertexCos[(int) eed->v1->tmp.l]);
124                                 glVertex3fv(emdm->vertexCos[(int) eed->v2->tmp.l]);
125                         }
126                 }
127                 glEnd();
128         }
129         else {
130                 glBegin(GL_LINES);
131                 for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
132                         if (!setDrawOptions || setDrawOptions(userData, i)) {
133                                 glVertex3fv(eed->v1->co);
134                                 glVertex3fv(eed->v2->co);
135                         }
136                 }
137                 glEnd();
138         }
139 }
140 static void emDM_drawEdges(
141                 DerivedMesh *dm,
142                 int UNUSED(drawLooseEdges),
143                 int UNUSED(drawAllEdges))
144 {
145         emDM_drawMappedEdges(dm, NULL, NULL);
146 }
147
148 static void emDM_drawMappedEdgesInterp(
149                 DerivedMesh *dm,
150                 int (*setDrawOptions)(void *userData, int index),
151                 void (*setDrawInterpOptions)(void *userData, int index, float t),
152                 void *userData)
153 {
154         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
155         EditEdge *eed;
156         int i;
157
158         if (emdm->vertexCos) {
159                 EditVert *eve;
160
161                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
162                         eve->tmp.l = (intptr_t) i++;
163
164                 glBegin(GL_LINES);
165                 for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
166                         if (!setDrawOptions || setDrawOptions(userData, i)) {
167                                 setDrawInterpOptions(userData, i, 0.0);
168                                 glVertex3fv(emdm->vertexCos[(int) eed->v1->tmp.l]);
169                                 setDrawInterpOptions(userData, i, 1.0);
170                                 glVertex3fv(emdm->vertexCos[(int) eed->v2->tmp.l]);
171                         }
172                 }
173                 glEnd();
174         }
175         else {
176                 glBegin(GL_LINES);
177                 for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
178                         if (!setDrawOptions || setDrawOptions(userData, i)) {
179                                 setDrawInterpOptions(userData, i, 0.0);
180                                 glVertex3fv(eed->v1->co);
181                                 setDrawInterpOptions(userData, i, 1.0);
182                                 glVertex3fv(eed->v2->co);
183                         }
184                 }
185                 glEnd();
186         }
187 }
188
189 static void emDM_drawUVEdges(DerivedMesh *dm)
190 {
191         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
192         EditFace *efa;
193         MTFace *tf;
194
195         glBegin(GL_LINES);
196         for (efa= emdm->em->faces.first; efa; efa= efa->next) {
197                 tf = CustomData_em_get(&emdm->em->fdata, efa->data, CD_MTFACE);
198
199                 if (tf && !(efa->h)) {
200                         glVertex2fv(tf->uv[0]);
201                         glVertex2fv(tf->uv[1]);
202
203                         glVertex2fv(tf->uv[1]);
204                         glVertex2fv(tf->uv[2]);
205
206                         if (!efa->v4) {
207                                 glVertex2fv(tf->uv[2]);
208                                 glVertex2fv(tf->uv[0]);
209                         }
210                         else {
211                                 glVertex2fv(tf->uv[2]);
212                                 glVertex2fv(tf->uv[3]);
213                                 glVertex2fv(tf->uv[3]);
214                                 glVertex2fv(tf->uv[0]);
215                         }
216                 }
217         }
218         glEnd();
219 }
220
221 static void emDM__calcFaceCent(EditFace *efa, float cent[3], float (*vertexCos)[3])
222 {
223         if (vertexCos) {
224                 copy_v3_v3(cent, vertexCos[(int) efa->v1->tmp.l]);
225                 add_v3_v3(cent, vertexCos[(int) efa->v2->tmp.l]);
226                 add_v3_v3(cent, vertexCos[(int) efa->v3->tmp.l]);
227                 if (efa->v4) add_v3_v3(cent, vertexCos[(int) efa->v4->tmp.l]);
228         }
229         else {
230                 copy_v3_v3(cent, efa->v1->co);
231                 add_v3_v3(cent, efa->v2->co);
232                 add_v3_v3(cent, efa->v3->co);
233                 if (efa->v4) add_v3_v3(cent, efa->v4->co);
234         }
235
236         if (efa->v4) {
237                 mul_v3_fl(cent, 0.25f);
238         }
239         else {
240                 mul_v3_fl(cent, 0.33333333333f);
241         }
242 }
243
244 static void emDM_foreachMappedFaceCenter(
245                 DerivedMesh *dm,
246                 void (*func)(void *userData, int index, float *co, float *no),
247                 void *userData)
248 {
249         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
250         EditVert *eve;
251         EditFace *efa;
252         float cent[3];
253         int i;
254
255         if (emdm->vertexCos) {
256                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
257                         eve->tmp.l = (intptr_t) i++;
258         }
259
260         for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
261                 emDM__calcFaceCent(efa, cent, emdm->vertexCos);
262                 func(userData, i, cent, emdm->vertexCos?emdm->faceNos[i]:efa->n);
263         }
264 }
265
266 /* note, material function is ignored for now. */
267 static void emDM_drawMappedFaces(
268                 DerivedMesh *dm,
269                 int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r),
270                 int (*setMaterial)(int, void *attribs),
271                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
272                 void *userData, int UNUSED(useColors))
273 {
274         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
275         EditFace *efa;
276         int i, draw, flush;
277         const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
278
279         /* GL_ZERO is used to detect if drawing has started or not */
280         GLenum poly_prev= GL_ZERO;
281         GLenum shade_prev= GL_ZERO;
282
283         (void)setMaterial; /* UNUSED */
284
285         /* currently unused -- each original face is handled separately */
286         (void)compareDrawOptions;
287
288         if (emdm->vertexCos) {
289                 /* add direct access */
290                 float (*vertexCos)[3]= emdm->vertexCos;
291                 float (*vertexNos)[3]= emdm->vertexNos;
292                 float (*faceNos)[3]=   emdm->faceNos;
293                 EditVert *eve;
294
295                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
296                         eve->tmp.l = (intptr_t) i++;
297
298                 for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
299                         int drawSmooth = (efa->flag & ME_SMOOTH);
300                         draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth);
301                         if (draw) {
302                                 const GLenum poly_type= efa->v4 ? GL_QUADS:GL_TRIANGLES;
303                                 if (draw==2) { /* enabled with stipple */
304
305                                         if (poly_prev != GL_ZERO) glEnd();
306                                         poly_prev= GL_ZERO; /* force glBegin */
307
308                                         glEnable(GL_POLYGON_STIPPLE);
309                                         glPolygonStipple(stipple_quarttone);
310                                 }
311
312                                 if (skip_normals) {
313                                         if (poly_type != poly_prev) {
314                                                 if (poly_prev != GL_ZERO) glEnd();
315                                                 glBegin((poly_prev= poly_type));
316                                         }
317                                         glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
318                                         glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
319                                         glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
320                                         if (poly_type == GL_QUADS) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
321                                 }
322                                 else {
323                                         const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
324                                         if (shade_type != shade_prev) {
325                                                 if (poly_prev != GL_ZERO) glEnd();
326                                                 glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
327                                                 glBegin((poly_prev= poly_type));
328                                         }
329                                         else if (poly_type != poly_prev) {
330                                                 if (poly_prev != GL_ZERO) glEnd();
331                                                 glBegin((poly_prev= poly_type));
332                                         }
333
334                                         if (!drawSmooth) {
335                                                 glNormal3fv(faceNos[i]);
336                                                 glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
337                                                 glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
338                                                 glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
339                                                 if (poly_type == GL_QUADS) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
340                                         }
341                                         else {
342                                                 glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
343                                                 glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
344                                                 glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
345                                                 glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
346                                                 glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
347                                                 glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
348                                                 if (poly_type == GL_QUADS) {
349                                                         glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
350                                                         glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
351                                                 }
352                                         }
353                                 }
354
355                                 flush= (draw==2);
356                                 if (!skip_normals && !flush && efa->next)
357                                         flush|= efa->mat_nr != efa->next->mat_nr;
358
359                                 if (flush) {
360                                         glEnd();
361                                         poly_prev= GL_ZERO; /* force glBegin */
362
363                                         glDisable(GL_POLYGON_STIPPLE);
364                                 }
365                         }
366                 }
367         }
368         else {
369                 for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
370                         int drawSmooth = (efa->flag & ME_SMOOTH);
371                         draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth);
372                         if (draw) {
373                                 const GLenum poly_type= efa->v4 ? GL_QUADS:GL_TRIANGLES;
374                                 if (draw==2) { /* enabled with stipple */
375
376                                         if (poly_prev != GL_ZERO) glEnd();
377                                         poly_prev= GL_ZERO; /* force glBegin */
378
379                                         glEnable(GL_POLYGON_STIPPLE);
380                                         glPolygonStipple(stipple_quarttone);
381                                 }
382
383                                 if (skip_normals) {
384                                         if (poly_type != poly_prev) {
385                                                 if (poly_prev != GL_ZERO) glEnd();
386                                                 glBegin((poly_prev= poly_type));
387                                         }
388                                         glVertex3fv(efa->v1->co);
389                                         glVertex3fv(efa->v2->co);
390                                         glVertex3fv(efa->v3->co);
391                                         if (poly_type == GL_QUADS) glVertex3fv(efa->v4->co);
392                                 }
393                                 else {
394                                         const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
395                                         if (shade_type != shade_prev) {
396                                                 if (poly_prev != GL_ZERO) glEnd();
397                                                 glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
398                                                 glBegin((poly_prev= poly_type));
399                                         }
400                                         else if (poly_type != poly_prev) {
401                                                 if (poly_prev != GL_ZERO) glEnd();
402                                                 glBegin((poly_prev= poly_type));
403                                         }
404
405                                         if (!drawSmooth) {
406                                                 glNormal3fv(efa->n);
407                                                 glVertex3fv(efa->v1->co);
408                                                 glVertex3fv(efa->v2->co);
409                                                 glVertex3fv(efa->v3->co);
410                                                 if (poly_type == GL_QUADS) glVertex3fv(efa->v4->co);
411                                         }
412                                         else {
413                                                 glNormal3fv(efa->v1->no);
414                                                 glVertex3fv(efa->v1->co);
415                                                 glNormal3fv(efa->v2->no);
416                                                 glVertex3fv(efa->v2->co);
417                                                 glNormal3fv(efa->v3->no);
418                                                 glVertex3fv(efa->v3->co);
419                                                 if (poly_type == GL_QUADS) {
420                                                         glNormal3fv(efa->v4->no);
421                                                         glVertex3fv(efa->v4->co);
422                                                 }
423                                         }
424                                 }
425
426                                 flush= (draw==2);
427                                 if (!skip_normals && !flush && efa->next)
428                                         flush|= efa->mat_nr != efa->next->mat_nr;
429
430                                 if (flush) {
431                                         glEnd();
432                                         poly_prev= GL_ZERO; /* force glBegin */
433
434                                         glDisable(GL_POLYGON_STIPPLE);
435                                 }
436                         }
437                 }
438         }
439
440         /* if non zero we know a face was rendered */
441         if (poly_prev != GL_ZERO) glEnd();
442 }
443
444 static void emDM_drawFacesTex_common(
445                 DerivedMesh *dm,
446                 int (*drawParams)(MTFace *tface, int has_mcol, int matnr),
447                 int (*drawParamsMapped)(void *userData, int index),
448                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
449                 void *userData)
450 {
451         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
452         EditMesh *em= emdm->em;
453         float (*vertexCos)[3]= emdm->vertexCos;
454         float (*vertexNos)[3]= emdm->vertexNos;
455         EditFace *efa;
456         int i;
457
458         (void) compareDrawOptions;
459
460         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
461         glShadeModel(GL_SMOOTH);
462
463         if (vertexCos) {
464                 EditVert *eve;
465
466                 for (i=0,eve=em->verts.first; eve; eve= eve->next)
467                         eve->tmp.l = (intptr_t) i++;
468
469                 for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
470                         MTFace *tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
471                         MCol *mcol= CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
472                         unsigned char *cp= NULL;
473                         int drawSmooth= (efa->flag & ME_SMOOTH);
474                         int flag;
475
476                         if (drawParams)
477                                 flag= drawParams(tf, (mcol != NULL), efa->mat_nr);
478                         else if (drawParamsMapped)
479                                 flag= drawParamsMapped(userData, i);
480                         else
481                                 flag= 1;
482
483                         if (flag != 0) { /* flag 0 == the face is hidden or invisible */
484
485                                 /* we always want smooth here since otherwise vertex colors dont interpolate */
486                                 if (mcol) {
487                                         if (flag==1) {
488                                                 cp= (unsigned char*)mcol;
489                                         }
490                                 }
491                                 else {
492                                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
493                                 }
494
495                                 glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
496                                 if (!drawSmooth) {
497                                         glNormal3fv(emdm->faceNos[i]);
498
499                                         if (tf) glTexCoord2fv(tf->uv[0]);
500                                         if (cp) glColor3ub(cp[3], cp[2], cp[1]);
501                                         glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
502
503                                         if (tf) glTexCoord2fv(tf->uv[1]);
504                                         if (cp) glColor3ub(cp[7], cp[6], cp[5]);
505                                         glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
506
507                                         if (tf) glTexCoord2fv(tf->uv[2]);
508                                         if (cp) glColor3ub(cp[11], cp[10], cp[9]);
509                                         glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
510
511                                         if (efa->v4) {
512                                                 if (tf) glTexCoord2fv(tf->uv[3]);
513                                                 if (cp) glColor3ub(cp[15], cp[14], cp[13]);
514                                                 glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
515                                         }
516                                 }
517                                 else {
518                                         if (tf) glTexCoord2fv(tf->uv[0]);
519                                         if (cp) glColor3ub(cp[3], cp[2], cp[1]);
520                                         glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
521                                         glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
522
523                                         if (tf) glTexCoord2fv(tf->uv[1]);
524                                         if (cp) glColor3ub(cp[7], cp[6], cp[5]);
525                                         glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
526                                         glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
527
528                                         if (tf) glTexCoord2fv(tf->uv[2]);
529                                         if (cp) glColor3ub(cp[11], cp[10], cp[9]);
530                                         glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
531                                         glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
532
533                                         if (efa->v4) {
534                                                 if (tf) glTexCoord2fv(tf->uv[3]);
535                                                 if (cp) glColor3ub(cp[15], cp[14], cp[13]);
536                                                 glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
537                                                 glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
538                                         }
539                                 }
540                                 glEnd();
541                         }
542                 }
543         }
544         else {
545                 for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
546                         MTFace *tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
547                         MCol *mcol= CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
548                         unsigned char *cp= NULL;
549                         int drawSmooth= (efa->flag & ME_SMOOTH);
550                         int flag;
551
552                         if (drawParams)
553                                 flag= drawParams(tf, (mcol != NULL), efa->mat_nr);
554                         else if (drawParamsMapped)
555                                 flag= drawParamsMapped(userData, i);
556                         else
557                                 flag= 1;
558
559                         if (flag != 0) { /* flag 0 == the face is hidden or invisible */
560
561                                 /* we always want smooth here since otherwise vertex colors dont interpolate */
562                                 if (mcol) {
563                                         if (flag==1) {
564                                                 cp= (unsigned char*)mcol;
565                                         }
566                                 }
567                                 else {
568                                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
569                                 }
570
571                                 glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
572                                 if (!drawSmooth) {
573                                         glNormal3fv(efa->n);
574
575                                         if (tf) glTexCoord2fv(tf->uv[0]);
576                                         if (cp) glColor3ub(cp[3], cp[2], cp[1]);
577                                         glVertex3fv(efa->v1->co);
578
579                                         if (tf) glTexCoord2fv(tf->uv[1]);
580                                         if (cp) glColor3ub(cp[7], cp[6], cp[5]);
581                                         glVertex3fv(efa->v2->co);
582
583                                         if (tf) glTexCoord2fv(tf->uv[2]);
584                                         if (cp) glColor3ub(cp[11], cp[10], cp[9]);
585                                         glVertex3fv(efa->v3->co);
586
587                                         if (efa->v4) {
588                                                 if (tf) glTexCoord2fv(tf->uv[3]);
589                                                 if (cp) glColor3ub(cp[15], cp[14], cp[13]);
590                                                 glVertex3fv(efa->v4->co);
591                                         }
592                                 }
593                                 else {
594                                         if (tf) glTexCoord2fv(tf->uv[0]);
595                                         if (cp) glColor3ub(cp[3], cp[2], cp[1]);
596                                         glNormal3fv(efa->v1->no);
597                                         glVertex3fv(efa->v1->co);
598
599                                         if (tf) glTexCoord2fv(tf->uv[1]);
600                                         if (cp) glColor3ub(cp[7], cp[6], cp[5]);
601                                         glNormal3fv(efa->v2->no);
602                                         glVertex3fv(efa->v2->co);
603
604                                         if (tf) glTexCoord2fv(tf->uv[2]);
605                                         if (cp) glColor3ub(cp[11], cp[10], cp[9]);
606                                         glNormal3fv(efa->v3->no);
607                                         glVertex3fv(efa->v3->co);
608
609                                         if (efa->v4) {
610                                                 if (tf) glTexCoord2fv(tf->uv[3]);
611                                                 if (cp) glColor3ub(cp[15], cp[14], cp[13]);
612                                                 glNormal3fv(efa->v4->no);
613                                                 glVertex3fv(efa->v4->co);
614                                         }
615                                 }
616                                 glEnd();
617                         }
618                 }
619         }
620 }
621
622 static void emDM_drawFacesTex(
623                 DerivedMesh *dm,
624                 int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr),
625                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
626                 void *userData)
627 {
628         emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
629 }
630
631 static void emDM_drawMappedFacesTex(
632                 DerivedMesh *dm,
633                 int (*setDrawOptions)(void *userData, int index),
634                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
635                 void *userData)
636 {
637         emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
638 }
639
640 static void emDM_drawMappedFacesGLSL(
641                 DerivedMesh *dm,
642                 int (*setMaterial)(int, void *attribs),
643                 int (*setDrawOptions)(void *userData, int index),
644                 void *userData)
645 {
646         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
647         EditMesh *em= emdm->em;
648         float (*vertexCos)[3]= emdm->vertexCos;
649         float (*vertexNos)[3]= emdm->vertexNos;
650         EditVert *eve;
651         EditFace *efa;
652         DMVertexAttribs attribs= {{{0}}};
653         GPUVertexAttribs gattribs;
654         /* int tfoffset; */ /* UNUSED */
655         int i, b, matnr, new_matnr, dodraw /* , layer */ /* UNUSED */;
656
657         dodraw = 0;
658         matnr = -1;
659
660         /* layer = CustomData_get_layer_index(&em->fdata, CD_MTFACE); */ /* UNUSED */
661         /* tfoffset = (layer == -1)? -1: em->fdata.layers[layer].offset; */ /* UNUSED */
662
663         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
664         glShadeModel(GL_SMOOTH);
665
666         for (i=0,eve=em->verts.first; eve; eve= eve->next)
667                 eve->tmp.l = (intptr_t) i++;
668
669 #define PASSATTRIB(efa, eve, vert) {                                                                                    \
670         if (attribs.totorco) {                                                                                                          \
671                 float *orco = attribs.orco.array[eve->tmp.l];                                                   \
672                 glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
673         }                                                                                                                                                       \
674         for (b = 0; b < attribs.tottface; b++) {                                                                        \
675                 MTFace *_tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset);  \
676                 glVertexAttrib2fvARB(attribs.tface[b].glIndex, _tf->uv[vert]);                  \
677         }                                                                                                                                                       \
678         for (b = 0; b < attribs.totmcol; b++) {                                                                         \
679                 MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].emOffset);                \
680                 GLubyte col[4];                                                                                                                 \
681                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
682                 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
683         }                                                                                                                                                       \
684         if (attribs.tottang) {                                                                                                          \
685                 float *tang = attribs.tang.array[i*4 + vert];                                                   \
686                 glVertexAttrib4fvARB(attribs.tang.glIndex, tang);                                               \
687         }                                                                                                                                                       \
688 }
689
690         for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
691                 int drawSmooth= (efa->flag & ME_SMOOTH);
692
693                 if (setDrawOptions && !setDrawOptions(userData, i))
694                         continue;
695
696                 new_matnr = efa->mat_nr + 1;
697                 if (new_matnr != matnr) {
698                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
699                         if (dodraw)
700                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
701                 }
702
703                 if (dodraw) {
704                         glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
705                         if (!drawSmooth) {
706                                 if (vertexCos) glNormal3fv(emdm->faceNos[i]);
707                                 else glNormal3fv(efa->n);
708
709                                 PASSATTRIB(efa, efa->v1, 0);
710                                 if (vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
711                                 else glVertex3fv(efa->v1->co);
712
713                                 PASSATTRIB(efa, efa->v2, 1);
714                                 if (vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
715                                 else glVertex3fv(efa->v2->co);
716
717                                 PASSATTRIB(efa, efa->v3, 2);
718                                 if (vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
719                                 else glVertex3fv(efa->v3->co);
720
721                                 if (efa->v4) {
722                                         PASSATTRIB(efa, efa->v4, 3);
723                                         if (vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
724                                         else glVertex3fv(efa->v4->co);
725                                 }
726                         }
727                         else {
728                                 PASSATTRIB(efa, efa->v1, 0);
729                                 if (vertexCos) {
730                                         glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
731                                         glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
732                                 }
733                                 else {
734                                         glNormal3fv(efa->v1->no);
735                                         glVertex3fv(efa->v1->co);
736                                 }
737
738                                 PASSATTRIB(efa, efa->v2, 1);
739                                 if (vertexCos) {
740                                         glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
741                                         glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
742                                 }
743                                 else {
744                                         glNormal3fv(efa->v2->no);
745                                         glVertex3fv(efa->v2->co);
746                                 }
747
748                                 PASSATTRIB(efa, efa->v3, 2);
749                                 if (vertexCos) {
750                                         glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
751                                         glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
752                                 }
753                                 else {
754                                         glNormal3fv(efa->v3->no);
755                                         glVertex3fv(efa->v3->co);
756                                 }
757
758                                 if (efa->v4) {
759                                         PASSATTRIB(efa, efa->v4, 3);
760                                         if (vertexCos) {
761                                                 glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
762                                                 glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
763                                         }
764                                         else {
765                                                 glNormal3fv(efa->v4->no);
766                                                 glVertex3fv(efa->v4->co);
767                                         }
768                                 }
769                         }
770                         glEnd();
771                 }
772         }
773 #undef PASSATTRIB
774 }
775
776 static void emDM_drawFacesGLSL(
777                 DerivedMesh *dm,
778                 int (*setMaterial)(int, void *attribs))
779 {
780         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
781 }
782
783 static void emDM_drawMappedFacesMat(
784                 DerivedMesh *dm,
785                 void (*setMaterial)(void *userData, int, void *attribs),
786                 int (*setFace)(void *userData, int index), void *userData)
787 {
788         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
789         EditMesh *em= emdm->em;
790         float (*vertexCos)[3]= emdm->vertexCos;
791         float (*vertexNos)[3]= emdm->vertexNos;
792         EditVert *eve;
793         EditFace *efa;
794         DMVertexAttribs attribs= {{{0}}};
795         GPUVertexAttribs gattribs;
796         int i, b, matnr, new_matnr;
797
798         matnr = -1;
799
800         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
801         glShadeModel(GL_SMOOTH);
802
803         for (i=0,eve=em->verts.first; eve; eve= eve->next)
804                 eve->tmp.l = (intptr_t) i++;
805
806 #define PASSATTRIB(efa, eve, vert) {                                                                                    \
807         if (attribs.totorco) {                                                                                                          \
808                 float *orco = attribs.orco.array[eve->tmp.l];                                                   \
809                 if (attribs.orco.glTexco)                                                                                               \
810                         glTexCoord3fv(orco);                                                                                            \
811                 else                                                                                                                                    \
812                         glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                       \
813         }                                                                                                                                                       \
814         for (b = 0; b < attribs.tottface; b++) {                                                                        \
815                 MTFace *_tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset);  \
816                 if (attribs.tface[b].glTexco)                                                                                   \
817                         glTexCoord2fv(_tf->uv[vert]);                                                                           \
818                 else                                                                                                                                    \
819                         glVertexAttrib2fvARB(attribs.tface[b].glIndex, _tf->uv[vert]);          \
820         }                                                                                                                                                       \
821         for (b = 0; b < attribs.totmcol; b++) {                                                                         \
822                 MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].emOffset);                \
823                 GLubyte col[4];                                                                                                                 \
824                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
825                 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
826         }                                                                                                                                                       \
827         if (attribs.tottang) {                                                                                                          \
828                 float *tang = attribs.tang.array[i*4 + vert];                                                   \
829                 glVertexAttrib4fvARB(attribs.tang.glIndex, tang);                                               \
830         }                                                                                                                                                       \
831 }
832
833         for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
834                 int drawSmooth= (efa->flag & ME_SMOOTH);
835
836                 /* face hiding */
837                 if (setFace && !setFace(userData, i))
838                         continue;
839
840                 /* material */
841                 new_matnr = efa->mat_nr + 1;
842                 if (new_matnr != matnr) {
843                         setMaterial(userData, matnr = new_matnr, &gattribs);
844                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
845                 }
846
847                 /* face */
848                 glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
849                 if (!drawSmooth) {
850                         if (vertexCos) glNormal3fv(emdm->faceNos[i]);
851                         else glNormal3fv(efa->n);
852
853                         PASSATTRIB(efa, efa->v1, 0);
854                         if (vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
855                         else glVertex3fv(efa->v1->co);
856
857                         PASSATTRIB(efa, efa->v2, 1);
858                         if (vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
859                         else glVertex3fv(efa->v2->co);
860
861                         PASSATTRIB(efa, efa->v3, 2);
862                         if (vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
863                         else glVertex3fv(efa->v3->co);
864
865                         if (efa->v4) {
866                                 PASSATTRIB(efa, efa->v4, 3);
867                                 if (vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
868                                 else glVertex3fv(efa->v4->co);
869                         }
870                 }
871                 else {
872                         PASSATTRIB(efa, efa->v1, 0);
873                         if (vertexCos) {
874                                 glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
875                                 glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
876                         }
877                         else {
878                                 glNormal3fv(efa->v1->no);
879                                 glVertex3fv(efa->v1->co);
880                         }
881
882                         PASSATTRIB(efa, efa->v2, 1);
883                         if (vertexCos) {
884                                 glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
885                                 glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
886                         }
887                         else {
888                                 glNormal3fv(efa->v2->no);
889                                 glVertex3fv(efa->v2->co);
890                         }
891
892                         PASSATTRIB(efa, efa->v3, 2);
893                         if (vertexCos) {
894                                 glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
895                                 glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
896                         }
897                         else {
898                                 glNormal3fv(efa->v3->no);
899                                 glVertex3fv(efa->v3->co);
900                         }
901
902                         if (efa->v4) {
903                                 PASSATTRIB(efa, efa->v4, 3);
904                                 if (vertexCos) {
905                                         glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
906                                         glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
907                                 }
908                                 else {
909                                         glNormal3fv(efa->v4->no);
910                                         glVertex3fv(efa->v4->co);
911                                 }
912                         }
913                 }
914                 glEnd();
915         }
916 #undef PASSATTRIB
917 }
918
919 static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
920 {
921         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
922         EditVert *eve;
923         int i;
924
925         if (emdm->em->verts.first) {
926                 for (i=0,eve= emdm->em->verts.first; eve; i++,eve= eve->next) {
927                         if (emdm->vertexCos) {
928                                 DO_MINMAX(emdm->vertexCos[i], min_r, max_r);
929                         }
930                         else {
931                                 DO_MINMAX(eve->co, min_r, max_r);
932                         }
933                 }
934         }
935         else {
936                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
937         }
938 }
939 static int emDM_getNumVerts(DerivedMesh *dm)
940 {
941         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
942
943         return BLI_countlist(&emdm->em->verts);
944 }
945
946 static int emDM_getNumEdges(DerivedMesh *dm)
947 {
948         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
949
950         return BLI_countlist(&emdm->em->edges);
951 }
952
953 static int emDM_getNumFaces(DerivedMesh *dm)
954 {
955         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
956
957         return BLI_countlist(&emdm->em->faces);
958 }
959
960 static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
961 {
962         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
963         EditVert *eve;
964         int i;
965
966         for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
967                 if (emdm->vertexCos) {
968                         copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
969                 }
970                 else {
971                         copy_v3_v3(cos_r[i], eve->co);
972                 }
973         }
974 }
975
976 static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
977 {
978         EditVert *ev = ((EditMeshDerivedMesh *)dm)->em->verts.first;
979         int i;
980
981         for (i = 0; i < index; ++i) ev = ev->next;
982
983         copy_v3_v3(vert_r->co, ev->co);
984
985         normal_float_to_short_v3(vert_r->no, ev->no);
986
987         /* TODO what to do with vert_r->flag? */
988         vert_r->bweight = (unsigned char) (ev->bweight*255.0f);
989 }
990
991 static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
992 {
993         EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
994         EditEdge *ee = em->edges.first;
995         EditVert *ev, *v1, *v2;
996         int i;
997
998         for (i = 0; i < index; ++i) ee = ee->next;
999
1000         edge_r->crease = (unsigned char) (ee->crease*255.0f);
1001         edge_r->bweight = (unsigned char) (ee->bweight*255.0f);
1002         /* TODO what to do with edge_r->flag? */
1003         edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
1004         if (ee->seam) edge_r->flag |= ME_SEAM;
1005         if (ee->sharp) edge_r->flag |= ME_SHARP;
1006 #if 0
1007         /* this needs setup of f2 field */
1008         if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
1009 #endif
1010
1011         /* goddamn, we have to search all verts to find indices */
1012         v1 = ee->v1;
1013         v2 = ee->v2;
1014         for (i = 0, ev = em->verts.first; v1 || v2; i++, ev = ev->next) {
1015                 if (ev == v1) {
1016                         edge_r->v1 = i;
1017                         v1 = NULL;
1018                 }
1019                 if (ev == v2) {
1020                         edge_r->v2 = i;
1021                         v2 = NULL;
1022                 }
1023         }
1024 }
1025
1026 static void emDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
1027 {
1028         EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
1029         EditFace *ef = em->faces.first;
1030         EditVert *ev, *v1, *v2, *v3, *v4;
1031         int i;
1032
1033         for (i = 0; i < index; ++i) ef = ef->next;
1034
1035         face_r->mat_nr = ef->mat_nr;
1036         face_r->flag = ef->flag;
1037
1038         /* goddamn, we have to search all verts to find indices */
1039         v1 = ef->v1;
1040         v2 = ef->v2;
1041         v3 = ef->v3;
1042         v4 = ef->v4;
1043         if (!v4) face_r->v4 = 0;
1044
1045         for (i = 0, ev = em->verts.first; v1 || v2 || v3 || v4;
1046                 i++, ev = ev->next) {
1047                 if (ev == v1) {
1048                         face_r->v1 = i;
1049                         v1 = NULL;
1050                 }
1051                 if (ev == v2) {
1052                         face_r->v2 = i;
1053                         v2 = NULL;
1054                 }
1055                 if (ev == v3) {
1056                         face_r->v3 = i;
1057                         v3 = NULL;
1058                 }
1059                 if (ev == v4) {
1060                         face_r->v4 = i;
1061                         v4 = NULL;
1062                 }
1063         }
1064
1065         test_index_face(face_r, NULL, 0, ef->v4?4:3);
1066 }
1067
1068 static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
1069 {
1070         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
1071         EditVert *ev = emdm->em->verts.first;
1072         int i;
1073
1074         for (i=0; ev; ev = ev->next, ++vert_r, ++i) {
1075                 if (emdm->vertexCos)
1076                         copy_v3_v3(vert_r->co, emdm->vertexCos[i]);
1077                 else
1078                         copy_v3_v3(vert_r->co, ev->co);
1079
1080                 normal_float_to_short_v3(vert_r->no, ev->no);
1081
1082                 /* TODO what to do with vert_r->flag? */
1083                 vert_r->flag = 0;
1084                 vert_r->bweight = (unsigned char) (ev->bweight*255.0f);
1085         }
1086 }
1087
1088 static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
1089 {
1090         EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
1091         EditEdge *ee = em->edges.first;
1092         EditVert *ev;
1093         int i;
1094
1095         /* store vertex indices in tmp union */
1096         for (ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
1097                 ev->tmp.l = (intptr_t) i;
1098
1099         for ( ; ee; ee = ee->next, ++edge_r) {
1100                 edge_r->crease = (unsigned char) (ee->crease*255.0f);
1101                 edge_r->bweight = (unsigned char) (ee->bweight*255.0f);
1102                 /* TODO what to do with edge_r->flag? */
1103                 edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
1104                 if (ee->seam) edge_r->flag |= ME_SEAM;
1105                 if (ee->sharp) edge_r->flag |= ME_SHARP;
1106 #if 0
1107                 /* this needs setup of f2 field */
1108                 if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
1109 #endif
1110
1111                 edge_r->v1 = (int)ee->v1->tmp.l;
1112                 edge_r->v2 = (int)ee->v2->tmp.l;
1113         }
1114 }
1115
1116 static void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
1117 {
1118         EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
1119         EditFace *ef = em->faces.first;
1120         EditVert *ev;
1121         int i;
1122
1123         /* store vertexes indices in tmp union */
1124         for (ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
1125                 ev->tmp.l = (intptr_t) i;
1126
1127         for ( ; ef; ef = ef->next, ++face_r) {
1128                 face_r->mat_nr = ef->mat_nr;
1129                 face_r->flag = ef->flag;
1130
1131                 face_r->v1 = (int)ef->v1->tmp.l;
1132                 face_r->v2 = (int)ef->v2->tmp.l;
1133                 face_r->v3 = (int)ef->v3->tmp.l;
1134                 if (ef->v4) face_r->v4 = (int)ef->v4->tmp.l;
1135                 else face_r->v4 = 0;
1136
1137                 test_index_face(face_r, NULL, 0, ef->v4?4:3);
1138         }
1139 }
1140
1141 static void *emDM_getFaceDataArray(DerivedMesh *dm, int type)
1142 {
1143         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
1144         EditMesh *em= emdm->em;
1145         EditFace *efa;
1146         char *data, *emdata;
1147         void *datalayer;
1148         int index, size;
1149
1150         datalayer = DM_get_face_data_layer(dm, type);
1151         if (datalayer)
1152                 return datalayer;
1153
1154         /* layers are store per face for editmesh, we convert to a temporary
1155          * data layer array in the derivedmesh when these are requested */
1156         if (type == CD_MTFACE || type == CD_MCOL) {
1157                 index = CustomData_get_layer_index(&em->fdata, type);
1158
1159                 if (index != -1) {
1160                         /* int offset = em->fdata.layers[index].offset; */ /* UNUSED */
1161                         size = CustomData_sizeof(type);
1162
1163                         DM_add_face_layer(dm, type, CD_CALLOC, NULL);
1164                         index = CustomData_get_layer_index(&dm->faceData, type);
1165                         dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1166
1167                         data = datalayer = DM_get_face_data_layer(dm, type);
1168                         for (efa=em->faces.first; efa; efa=efa->next, data+=size) {
1169                                 emdata = CustomData_em_get(&em->fdata, efa->data, type);
1170                                 memcpy(data, emdata, size);
1171                         }
1172                 }
1173         }
1174
1175         return datalayer;
1176 }
1177
1178 static void emDM_release(DerivedMesh *dm)
1179 {
1180         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
1181
1182         if (DM_release(dm)) {
1183                 if (emdm->vertexCos) {
1184                         MEM_freeN(emdm->vertexCos);
1185                         MEM_freeN(emdm->vertexNos);
1186                         MEM_freeN(emdm->faceNos);
1187                 }
1188
1189                 MEM_freeN(emdm);
1190         }
1191 }
1192
1193 DerivedMesh *editmesh_get_derived(
1194                 EditMesh *em,
1195                 float (*vertexCos)[3])
1196 {
1197         EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm");
1198
1199         DM_init(&emdm->dm, DM_TYPE_EDITMESH, BLI_countlist(&em->verts),
1200                                          BLI_countlist(&em->edges), BLI_countlist(&em->faces));
1201
1202         emdm->dm.getMinMax = emDM_getMinMax;
1203
1204         emdm->dm.getNumVerts = emDM_getNumVerts;
1205         emdm->dm.getNumEdges = emDM_getNumEdges;
1206         emdm->dm.getNumFaces = emDM_getNumFaces;
1207
1208         emdm->dm.getVertCos = emDM_getVertCos;
1209
1210         emdm->dm.getVert = emDM_getVert;
1211         emdm->dm.getEdge = emDM_getEdge;
1212         emdm->dm.getFace = emDM_getFace;
1213         emdm->dm.copyVertArray = emDM_copyVertArray;
1214         emdm->dm.copyEdgeArray = emDM_copyEdgeArray;
1215         emdm->dm.copyFaceArray = emDM_copyFaceArray;
1216         emdm->dm.getFaceDataArray = emDM_getFaceDataArray;
1217
1218         emdm->dm.foreachMappedVert = emDM_foreachMappedVert;
1219         emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
1220         emdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
1221
1222         emdm->dm.drawEdges = emDM_drawEdges;
1223         emdm->dm.drawMappedEdges = emDM_drawMappedEdges;
1224         emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
1225         emdm->dm.drawMappedFaces = emDM_drawMappedFaces;
1226         emdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
1227         emdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
1228         emdm->dm.drawFacesTex = emDM_drawFacesTex;
1229         emdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
1230         emdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
1231         emdm->dm.drawUVEdges = emDM_drawUVEdges;
1232
1233         emdm->dm.release = emDM_release;
1234
1235         emdm->em = em;
1236         emdm->vertexCos = vertexCos;
1237
1238         if (CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) {
1239                 EditVert *eve;
1240                 int i;
1241
1242                 DM_add_vert_layer(&emdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
1243
1244                 for (eve = em->verts.first, i = 0; eve; eve = eve->next, ++i)
1245                         DM_set_vert_data(&emdm->dm, i, CD_MDEFORMVERT,
1246                                                          CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT));
1247         }
1248
1249         if (vertexCos) {
1250                 EditVert *eve;
1251                 EditFace *efa;
1252                 int totface = BLI_countlist(&em->faces);
1253                 int i;
1254
1255                 for (i=0,eve=em->verts.first; eve; eve= eve->next)
1256                         eve->tmp.l = (intptr_t) i++;
1257
1258                 emdm->vertexNos = MEM_callocN(sizeof(*emdm->vertexNos)*i, "emdm_vno");
1259                 emdm->faceNos = MEM_mallocN(sizeof(*emdm->faceNos)*totface, "emdm_vno");
1260
1261                 for (i=0, efa= em->faces.first; efa; i++, efa=efa->next) {
1262                         float *v1 = vertexCos[(int) efa->v1->tmp.l];
1263                         float *v2 = vertexCos[(int) efa->v2->tmp.l];
1264                         float *v3 = vertexCos[(int) efa->v3->tmp.l];
1265                         float *no = emdm->faceNos[i];
1266
1267                         if (efa->v4) {
1268                                 float *v4 = vertexCos[(int) efa->v4->tmp.l];
1269
1270                                 normal_quad_v3( no,v1, v2, v3, v4);
1271                                 add_v3_v3(emdm->vertexNos[(int) efa->v4->tmp.l], no);
1272                         }
1273                         else {
1274                                 normal_tri_v3( no,v1, v2, v3);
1275                         }
1276
1277                         add_v3_v3(emdm->vertexNos[(int) efa->v1->tmp.l], no);
1278                         add_v3_v3(emdm->vertexNos[(int) efa->v2->tmp.l], no);
1279                         add_v3_v3(emdm->vertexNos[(int) efa->v3->tmp.l], no);
1280                 }
1281
1282                 for (i=0, eve= em->verts.first; eve; i++, eve=eve->next) {
1283                         float *no = emdm->vertexNos[i];
1284                         /* following Mesh convention; we use vertex coordinate itself
1285                          * for normal in this case */
1286                         if (normalize_v3(no) == 0.0f) {
1287                                 normalize_v3_v3(no, vertexCos[i]);
1288                         }
1289                 }
1290         }
1291
1292         return (DerivedMesh*) emdm;
1293 }
1294