UV Editor: added proportional edit buttons to the header.
[blender.git] / source / blender / blenkernel / intern / cdderivedmesh.c
1 /*
2 * $Id$
3 *
4 * ***** BEGIN GPL LICENSE BLOCK *****
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software  Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 *
20 * The Original Code is Copyright (C) 2006 Blender Foundation.
21 * All rights reserved.
22 *
23 * The Original Code is: all of this file.
24 *
25 * Contributor(s): Ben Batt <benbatt@gmail.com>
26 *
27 * ***** END GPL LICENSE BLOCK *****
28 *
29 * Implementation of CDDerivedMesh.
30 *
31 * BKE_cdderivedmesh.h contains the function prototypes for this file.
32 *
33 */ 
34
35 /* TODO maybe BIF_gl.h should include string.h? */
36 #include <string.h>
37 #include "BIF_gl.h"
38
39 #include "BKE_cdderivedmesh.h"
40 #include "BKE_customdata.h"
41 #include "BKE_DerivedMesh.h"
42 #include "BKE_displist.h"
43 #include "BKE_global.h"
44 #include "BKE_mesh.h"
45 #include "BKE_multires.h"
46 #include "BKE_utildefines.h"
47
48 #include "BLI_math.h"
49 #include "BLI_blenlib.h"
50 #include "BLI_edgehash.h"
51 #include "BLI_editVert.h"
52 #include "BLI_ghash.h"
53
54 #include "DNA_mesh_types.h"
55 #include "DNA_meshdata_types.h"
56 #include "DNA_modifier_types.h"
57 #include "DNA_object_fluidsim.h"
58 #include "DNA_object_types.h"
59 #include "DNA_scene_types.h"
60
61 #include "MEM_guardedalloc.h"
62
63 #include "gpu_buffers.h"
64 #include "GPU_draw.h"
65 #include "GPU_extensions.h"
66 #include "GPU_material.h"
67
68 #include <string.h>
69 #include <limits.h>
70 #include <math.h>
71
72 typedef struct {
73         DerivedMesh dm;
74
75         /* these point to data in the DerivedMesh custom data layers,
76            they are only here for efficiency and convenience **/
77         MVert *mvert;
78         MEdge *medge;
79         MFace *mface;
80 } CDDerivedMesh;
81
82 /**************** DerivedMesh interface functions ****************/
83 static int cdDM_getNumVerts(DerivedMesh *dm)
84 {
85         return dm->numVertData;
86 }
87
88 static int cdDM_getNumEdges(DerivedMesh *dm)
89 {
90         return dm->numEdgeData;
91 }
92
93 static int cdDM_getNumFaces(DerivedMesh *dm)
94 {
95         return dm->numFaceData;
96 }
97
98 static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
99 {
100         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
101         *vert_r = cddm->mvert[index];
102 }
103
104 static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
105 {
106         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
107         *edge_r = cddm->medge[index];
108 }
109
110 static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
111 {
112         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
113         *face_r = cddm->mface[index];
114 }
115
116 static void cdDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
117 {
118         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
119         memcpy(vert_r, cddm->mvert, sizeof(*vert_r) * dm->numVertData);
120 }
121
122 static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
123 {
124         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
125         memcpy(edge_r, cddm->medge, sizeof(*edge_r) * dm->numEdgeData);
126 }
127
128 static void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
129 {
130         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
131         memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData);
132 }
133
134 static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
135 {
136         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
137         int i;
138
139         if (dm->numVertData) {
140                 for (i=0; i<dm->numVertData; i++) {
141                         DO_MINMAX(cddm->mvert[i].co, min_r, max_r);
142                 }
143         } else {
144                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
145         }
146 }
147
148 static void cdDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
149 {
150         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
151
152         VECCOPY(co_r, cddm->mvert[index].co);
153 }
154
155 static void cdDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
156 {
157         MVert *mv = CDDM_get_verts(dm);
158         int i;
159
160         for(i = 0; i < dm->numVertData; i++, mv++)
161                 VECCOPY(cos_r[i], mv->co);
162 }
163
164 static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
165 {
166         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
167         short *no = cddm->mvert[index].no;
168
169         no_r[0] = no[0]/32767.f;
170         no_r[1] = no[1]/32767.f;
171         no_r[2] = no[2]/32767.f;
172 }
173
174 static void cdDM_drawVerts(DerivedMesh *dm)
175 {
176         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
177         MVert *mv = cddm->mvert;
178         int i;
179
180         if( GPU_buffer_legacy(dm) ) {
181                 glBegin(GL_POINTS);
182                 for(i = 0; i < dm->numVertData; i++, mv++)
183                         glVertex3fv(mv->co);
184                 glEnd();
185         }
186         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
187                 GPU_vertex_setup(dm);
188                 if( !GPU_buffer_legacy(dm) ) {
189                         glDrawArrays(GL_POINTS,0,dm->drawObject->nelements);
190                 }
191                 GPU_buffer_unbind();
192         }
193 }
194
195 static void cdDM_drawUVEdges(DerivedMesh *dm)
196 {
197         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
198         MFace *mf = cddm->mface;
199         MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
200         int i;
201
202         if(mf) {
203                 if( GPU_buffer_legacy(dm) ) {
204                         glBegin(GL_LINES);
205                         for(i = 0; i < dm->numFaceData; i++, mf++, tf++) {
206                                 if(!(mf->flag&ME_HIDE)) {
207                                         glVertex2fv(tf->uv[0]);
208                                         glVertex2fv(tf->uv[1]);
209
210                                         glVertex2fv(tf->uv[1]);
211                                         glVertex2fv(tf->uv[2]);
212
213                                         if(!mf->v4) {
214                                                 glVertex2fv(tf->uv[2]);
215                                                 glVertex2fv(tf->uv[0]);
216                                         } else {
217                                                 glVertex2fv(tf->uv[2]);
218                                                 glVertex2fv(tf->uv[3]);
219
220                                                 glVertex2fv(tf->uv[3]);
221                                                 glVertex2fv(tf->uv[0]);
222                                         }
223                                 }
224                         }
225                         glEnd();
226                 }
227                 else {
228                         int prevstart = 0;
229                         int prevdraw = 1;
230                         int draw = 1;
231                         int curpos = 0;
232
233                         GPU_uvedge_setup(dm);
234                         if( !GPU_buffer_legacy(dm) ) {
235                                 for(i = 0; i < dm->numFaceData; i++, mf++) {
236                                         if(mf->flag&ME_LOOSEEDGE) {
237                                                 draw = 1;
238                                         } 
239                                         else {
240                                                 draw = 0;
241                                         }
242                                         if( prevdraw != draw ) {
243                                                 if( prevdraw > 0 && (curpos-prevstart) > 0) {
244                                                         glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
245                                                 }
246                                                 prevstart = curpos;
247                                         }
248                                         if( mf->v4 ) {
249                                                 curpos += 8;
250                                         }
251                                         else {
252                                                 curpos += 6;
253                                         }
254                                         prevdraw = draw;
255                                 }
256                                 if( prevdraw > 0 && (curpos-prevstart) > 0 ) {
257                                         glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
258                                 }
259                         }
260                         GPU_buffer_unbind();
261                 }
262         }
263 }
264
265 static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
266 {
267         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
268         MVert *mvert = cddm->mvert;
269         MEdge *medge = cddm->medge;
270         int i;
271         
272         if( GPU_buffer_legacy(dm) ) {
273                 DEBUG_VBO( "Using legacy code. cdDM_drawEdges\n" );
274                 glBegin(GL_LINES);
275                 for(i = 0; i < dm->numEdgeData; i++, medge++) {
276                         if((medge->flag&ME_EDGEDRAW)
277                            && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
278                                 glVertex3fv(mvert[medge->v1].co);
279                                 glVertex3fv(mvert[medge->v2].co);
280                         }
281                 }
282                 glEnd();
283         }
284         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
285                 int prevstart = 0;
286                 int prevdraw = 1;
287                 int draw = 1;
288
289                 GPU_edge_setup(dm);
290                 if( !GPU_buffer_legacy(dm) ) {
291                         for(i = 0; i < dm->numEdgeData; i++, medge++) {
292                                 if((medge->flag&ME_EDGEDRAW)
293                                    && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
294                                         draw = 1;
295                                 } 
296                                 else {
297                                         draw = 0;
298                                 }
299                                 if( prevdraw != draw ) {
300                                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
301                                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
302                                         }
303                                         prevstart = i;
304                                 }
305                                 prevdraw = draw;
306                         }
307                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
308                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
309                         }
310                 }
311                 GPU_buffer_unbind();
312         }
313 }
314
315 static void cdDM_drawLooseEdges(DerivedMesh *dm)
316 {
317         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
318         MVert *mvert = cddm->mvert;
319         MEdge *medge = cddm->medge;
320         int i;
321
322         if( GPU_buffer_legacy(dm) ) {
323                 DEBUG_VBO( "Using legacy code. cdDM_drawLooseEdges\n" );
324                 glBegin(GL_LINES);
325                 for(i = 0; i < dm->numEdgeData; i++, medge++) {
326                         if(medge->flag&ME_LOOSEEDGE) {
327                                 glVertex3fv(mvert[medge->v1].co);
328                                 glVertex3fv(mvert[medge->v2].co);
329                         }
330                 }
331                 glEnd();
332         }
333         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
334                 int prevstart = 0;
335                 int prevdraw = 1;
336                 int draw = 1;
337
338                 GPU_edge_setup(dm);
339                 if( !GPU_buffer_legacy(dm) ) {
340                         for(i = 0; i < dm->numEdgeData; i++, medge++) {
341                                 if(medge->flag&ME_LOOSEEDGE) {
342                                         draw = 1;
343                                 } 
344                                 else {
345                                         draw = 0;
346                                 }
347                                 if( prevdraw != draw ) {
348                                         if( prevdraw > 0 && (i-prevstart) > 0) {
349                                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
350                                         }
351                                         prevstart = i;
352                                 }
353                                 prevdraw = draw;
354                         }
355                         if( prevdraw > 0 && (i-prevstart) > 0 ) {
356                                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
357                         }
358                 }
359                 GPU_buffer_unbind();
360         }
361 }
362
363 static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
364 {
365         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
366         MVert *mvert = cddm->mvert;
367         MFace *mface = cddm->mface;
368         float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
369         int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
370
371 #define PASSVERT(index) {                                               \
372         if(shademodel == GL_SMOOTH) {                           \
373                 short *no = mvert[index].no;                    \
374                 glNormal3sv(no);                                                \
375         }                                                                                       \
376         glVertex3fv(mvert[index].co);   \
377 }
378
379         if( GPU_buffer_legacy(dm) ) {
380                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" );
381                 glBegin(glmode = GL_QUADS);
382                 for(a = 0; a < dm->numFaceData; a++, mface++) {
383                         int new_glmode, new_matnr, new_shademodel;
384
385                         new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
386                         new_matnr = mface->mat_nr + 1;
387                         new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
388                         
389                         if(new_glmode != glmode || new_matnr != matnr
390                            || new_shademodel != shademodel) {
391                                 glEnd();
392
393                                 drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
394
395                                 glShadeModel(shademodel = new_shademodel);
396                                 glBegin(glmode = new_glmode);
397                         } 
398                         
399                         if(drawCurrentMat) {
400                                 if(shademodel == GL_FLAT) {
401                                         if (nors) {
402                                                 glNormal3fv(nors);
403                                         }
404                                         else {
405                                                 /* TODO make this better (cache facenormals as layer?) */
406                                                 float nor[3];
407                                                 if(mface->v4) {
408                                                         normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
409                                                 } else {
410                                                         normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
411                                                 }
412                                                 glNormal3fv(nor);
413                                         }
414                                 }
415
416                                 PASSVERT(mface->v1);
417                                 PASSVERT(mface->v2);
418                                 PASSVERT(mface->v3);
419                                 if(mface->v4) {
420                                         PASSVERT(mface->v4);
421                                 }
422                         }
423
424                         if(nors) nors += 3;
425                 }
426                 glEnd();
427         }
428         else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
429                 GPU_vertex_setup( dm );
430                 GPU_normal_setup( dm );
431                 if( !GPU_buffer_legacy(dm) ) {
432                         glShadeModel(GL_SMOOTH);
433                         for( a = 0; a < dm->drawObject->nmaterials; a++ ) {
434                                 if( setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL) )
435                                         glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start, dm->drawObject->materials[a].end-dm->drawObject->materials[a].start);
436                         }
437                 }
438                 GPU_buffer_unbind( );
439         }
440
441 #undef PASSVERT
442         glShadeModel(GL_FLAT);
443 }
444
445 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
446 {
447         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
448         int a, glmode;
449         unsigned char *cp1, *cp2;
450         MVert *mvert = cddm->mvert;
451         MFace *mface = cddm->mface;
452
453         cp1 = col1;
454         if(col2) {
455                 cp2 = col2;
456         } else {
457                 cp2 = NULL;
458                 useTwoSided = 0;
459         }
460
461         /* there's a conflict here... twosided colors versus culling...? */
462         /* defined by history, only texture faces have culling option */
463         /* we need that as mesh option builtin, next to double sided lighting */
464         if(col1 && col2)
465                 glEnable(GL_CULL_FACE);
466
467         if( GPU_buffer_legacy(dm) ) {
468                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" );
469                 glShadeModel(GL_SMOOTH);
470                 glBegin(glmode = GL_QUADS);
471                 for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
472                         int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
473
474                         if(new_glmode != glmode) {
475                                 glEnd();
476                                 glBegin(glmode = new_glmode);
477                         }
478                                 
479                         glColor3ub(cp1[0], cp1[1], cp1[2]);
480                         glVertex3fv(mvert[mface->v1].co);
481                         glColor3ub(cp1[4], cp1[5], cp1[6]);
482                         glVertex3fv(mvert[mface->v2].co);
483                         glColor3ub(cp1[8], cp1[9], cp1[10]);
484                         glVertex3fv(mvert[mface->v3].co);
485                         if(mface->v4) {
486                                 glColor3ub(cp1[12], cp1[13], cp1[14]);
487                                 glVertex3fv(mvert[mface->v4].co);
488                         }
489                                 
490                         if(useTwoSided) {
491                                 glColor3ub(cp2[8], cp2[9], cp2[10]);
492                                 glVertex3fv(mvert[mface->v3].co );
493                                 glColor3ub(cp2[4], cp2[5], cp2[6]);
494                                 glVertex3fv(mvert[mface->v2].co );
495                                 glColor3ub(cp2[0], cp2[1], cp2[2]);
496                                 glVertex3fv(mvert[mface->v1].co );
497                                 if(mface->v4) {
498                                         glColor3ub(cp2[12], cp2[13], cp2[14]);
499                                         glVertex3fv(mvert[mface->v4].co );
500                                 }
501                         }
502                         if(col2) cp2 += 16;
503                 }
504                 glEnd();
505         }
506         else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
507                 GPU_color4_upload(dm,cp1);
508                 GPU_vertex_setup(dm);
509                 GPU_color_setup(dm);
510                 if( !GPU_buffer_legacy(dm) ) {
511                         glShadeModel(GL_SMOOTH);
512                         glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
513
514                         if( useTwoSided ) {
515                                 GPU_color4_upload(dm,cp2);
516                                 GPU_color_setup(dm);
517                                 glCullFace(GL_FRONT);
518                                 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
519                                 glCullFace(GL_BACK);
520                         }
521                 }
522                 GPU_buffer_unbind();
523         }
524
525         glShadeModel(GL_FLAT);
526         glDisable(GL_CULL_FACE);
527 }
528
529 static void cdDM_drawFacesTex_common(DerivedMesh *dm,
530                int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
531                int (*drawParamsMapped)(void *userData, int index),
532                void *userData) 
533 {
534         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
535         MVert *mv = cddm->mvert;
536         MFace *mf = DM_get_face_data_layer(dm, CD_MFACE);
537         MCol *realcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL);
538         float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
539         MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
540         int i, j, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
541         int startFace = 0, lastFlag = 0xdeadbeef;
542         MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
543         if(!mcol)
544                 mcol = dm->getFaceDataArray(dm, CD_MCOL);
545
546         if( GPU_buffer_legacy(dm) ) {
547                 DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
548                 for(i = 0; i < dm->numFaceData; i++, mf++) {
549                         MVert *mvert;
550                         int flag;
551                         unsigned char *cp = NULL;
552
553                         if(drawParams) {
554                                 flag = drawParams(tf? &tf[i]: NULL, mcol? &mcol[i*4]: NULL, mf->mat_nr);
555                         }
556                         else {
557                                 if(index) {
558                                         orig = *index++;
559                                         if(orig == ORIGINDEX_NONE)              { if(nors) nors += 3; continue; }
560                                         if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
561                                         else    { if(nors) nors += 3; continue; }
562                                 }
563                                 else
564                                         if(drawParamsMapped) flag = drawParamsMapped(userData, i);
565                                         else    { if(nors) nors += 3; continue; }
566                         }
567                         
568                         if(flag != 0) {
569                                 if (flag==1 && mcol)
570                                         cp= (unsigned char*) &mcol[i*4];
571
572                                 if(!(mf->flag&ME_SMOOTH)) {
573                                         if (nors) {
574                                                 glNormal3fv(nors);
575                                         }
576                                         else {
577                                                 float nor[3];
578                                                 if(mf->v4) {
579                                                         normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
580                                                 } else {
581                                                         normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
582                                                 }
583                                                 glNormal3fv(nor);
584                                         }
585                                 }
586
587                                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
588                                 if(tf) glTexCoord2fv(tf[i].uv[0]);
589                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
590                                 mvert = &mv[mf->v1];
591                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
592                                 glVertex3fv(mvert->co);
593                                         
594                                 if(tf) glTexCoord2fv(tf[i].uv[1]);
595                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
596                                 mvert = &mv[mf->v2];
597                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
598                                 glVertex3fv(mvert->co);
599
600                                 if(tf) glTexCoord2fv(tf[i].uv[2]);
601                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
602                                 mvert = &mv[mf->v3];
603                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
604                                 glVertex3fv(mvert->co);
605
606                                 if(mf->v4) {
607                                         if(tf) glTexCoord2fv(tf[i].uv[3]);
608                                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
609                                         mvert = &mv[mf->v4];
610                                         if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
611                                         glVertex3fv(mvert->co);
612                                 }
613                                 glEnd();
614                         }
615                         
616                         if(nors) nors += 3;
617                 }
618         } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
619                 MCol *col = realcol;
620                 if(!col)
621                         col = mcol;
622
623                 GPU_vertex_setup( dm );
624                 GPU_normal_setup( dm );
625                 GPU_uv_setup( dm );
626                 if( col != 0 ) {
627                         /*if( realcol && dm->drawObject->colType == CD_TEXTURE_MCOL )  {
628                                 col = 0;
629                         } else if( mcol && dm->drawObject->colType == CD_MCOL ) {
630                                 col = 0;
631                         }
632                         
633                         if( col != 0 ) {*/
634                                 unsigned char *colors = MEM_mallocN(dm->getNumFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
635                                 for( i=0; i < dm->getNumFaces(dm); i++ ) {
636                                         for( j=0; j < 4; j++ ) {
637                                                 colors[i*12+j*3] = col[i*4+j].r;
638                                                 colors[i*12+j*3+1] = col[i*4+j].g;
639                                                 colors[i*12+j*3+2] = col[i*4+j].b;
640                                         }
641                                 }
642                                 GPU_color3_upload(dm,colors);
643                                 MEM_freeN(colors);
644                                 if(realcol)
645                                         dm->drawObject->colType = CD_TEXTURE_MCOL;
646                                 else if(mcol)
647                                         dm->drawObject->colType = CD_MCOL;
648                         //}
649                         GPU_color_setup( dm );
650                 }
651
652                 if( !GPU_buffer_legacy(dm) ) {
653                         glShadeModel( GL_SMOOTH );
654                         for(i = 0; i < dm->drawObject->nelements/3; i++) {
655                                 int actualFace = dm->drawObject->faceRemap[i];
656                                 int flag = 1;
657
658                                 if(drawParams) {
659                                         flag = drawParams(tf? &tf[actualFace]: NULL, mcol? &mcol[actualFace*4]: NULL, mf[actualFace].mat_nr);
660                                 }
661                                 else {
662                                         if(index) {
663                                                 orig = index[actualFace];
664                                                 if(drawParamsMapped)
665                                                         flag = drawParamsMapped(userData, orig);
666                                         }
667                                         else
668                                                 if(drawParamsMapped)
669                                                         flag = drawParamsMapped(userData, actualFace);
670                                 }
671                                 if( flag != lastFlag ) {
672                                         if( startFace < i ) {
673                                                 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
674                                                         if (lastFlag==1 && mcol)
675                                                                 GPU_color_switch(1);
676                                                         else
677                                                                 GPU_color_switch(0);
678                                                         glDrawArrays(GL_TRIANGLES,startFace*3,(i-startFace)*3);
679                                                 }
680                                         }
681                                         lastFlag = flag;
682                                         startFace = i;
683                                 }
684                         }
685                         if( startFace < dm->drawObject->nelements/3 ) {
686                                 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
687                                         if (lastFlag==1 && mcol)
688                                                 GPU_color_switch(1);
689                                         else
690                                                 GPU_color_switch(0);
691                                         glDrawArrays(GL_TRIANGLES,startFace*3,dm->drawObject->nelements-startFace*3);
692                                 }
693                         }
694                 }
695
696                 GPU_buffer_unbind();
697                 glShadeModel( GL_FLAT );
698         }
699 }
700
701 static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
702 {
703         cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
704 }
705
706 static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
707 {
708         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
709         MVert *mv = cddm->mvert;
710         MFace *mf = cddm->mface;
711         MCol *mc;
712         float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
713         int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
714
715
716         mc = DM_get_face_data_layer(dm, CD_ID_MCOL);
717         if(!mc)
718                 mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
719         if(!mc)
720                 mc = DM_get_face_data_layer(dm, CD_MCOL);
721
722         if( GPU_buffer_legacy(dm) ) {
723                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" );
724                 for(i = 0; i < dm->numFaceData; i++, mf++) {
725                         int drawSmooth = (mf->flag & ME_SMOOTH);
726
727                         if(index) {
728                                 orig = *index++;
729                                 if(setDrawOptions && orig == ORIGINDEX_NONE)
730                                         { if(nors) nors += 3; continue; }
731                         }
732                         else
733                                 orig = i;
734
735                         if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) {
736                                 unsigned char *cp = NULL;
737
738                                 if(useColors && mc)
739                                         cp = (unsigned char *)&mc[i * 4];
740
741                                 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
742                                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
743
744                                 if (!drawSmooth) {
745                                         if (nors) {
746                                                 glNormal3fv(nors);
747                                         }
748                                         else {
749                                                 float nor[3];
750                                                 if(mf->v4) {
751                                                         normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
752                                                 } else {
753                                                         normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
754                                                 }
755                                                 glNormal3fv(nor);
756                                         }
757
758                                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
759                                         glVertex3fv(mv[mf->v1].co);
760                                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
761                                         glVertex3fv(mv[mf->v2].co);
762                                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
763                                         glVertex3fv(mv[mf->v3].co);
764                                         if(mf->v4) {
765                                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
766                                                 glVertex3fv(mv[mf->v4].co);
767                                         }
768                                 } else {
769                                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
770                                         glNormal3sv(mv[mf->v1].no);
771                                         glVertex3fv(mv[mf->v1].co);
772                                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
773                                         glNormal3sv(mv[mf->v2].no);
774                                         glVertex3fv(mv[mf->v2].co);
775                                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
776                                         glNormal3sv(mv[mf->v3].no);
777                                         glVertex3fv(mv[mf->v3].co);
778                                         if(mf->v4) {
779                                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
780                                                 glNormal3sv(mv[mf->v4].no);
781                                                 glVertex3fv(mv[mf->v4].co);
782                                         }
783                                 }
784
785                                 glEnd();
786                         }
787                         
788                         if (nors) nors += 3;
789                 }
790         }
791         else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
792                 int state = 1;
793                 int prevstate = 1;
794                 int prevstart = 0;
795                 GPU_vertex_setup(dm);
796                 GPU_normal_setup(dm);
797                 if( useColors && mc )
798                         GPU_color_setup(dm);
799                 if( !GPU_buffer_legacy(dm) ) {
800                         glShadeModel(GL_SMOOTH);
801                         for( i = 0; i < dm->drawObject->nelements/3; i++ ) {
802                                 int actualFace = dm->drawObject->faceRemap[i];
803                                 int drawSmooth = (mf[actualFace].flag & ME_SMOOTH);
804                                 int dontdraw = 0;
805                                 if(index) {
806                                         orig = index[actualFace];
807                                         if(setDrawOptions && orig == ORIGINDEX_NONE)
808                                                 dontdraw = 1;
809                                 }
810                                 else
811                                         orig = i;
812                                 if( dontdraw ) {
813                                         state = 0;
814                                 }
815                                 else {
816                                         if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) {
817                                                 state = 1;
818                                         }
819                                         else {
820                                                 state = 0;
821                                         }
822                                 }
823                                 if( prevstate != state && prevstate == 1 ) {
824                                         if( i-prevstart > 0 ) {
825                                                 glDrawArrays(GL_TRIANGLES,prevstart*3,(i-prevstart)*3);
826                                         }
827                                         prevstart = i;
828                                 }
829                                 prevstate = state;
830                         }
831                         if(state==1) {
832                                 glDrawArrays(GL_TRIANGLES,prevstart*3,dm->drawObject->nelements-prevstart*3);
833                         }
834                         glShadeModel(GL_FLAT);
835                 }
836                 GPU_buffer_unbind();
837         }
838 }
839
840 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
841 {
842         cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
843 }
844
845 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
846 {
847         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
848         GPUVertexAttribs gattribs;
849         DMVertexAttribs attribs;
850         MVert *mvert = cddm->mvert;
851         MFace *mface = cddm->mface;
852         MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
853         float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
854         int a, b, dodraw, smoothnormal, matnr, new_matnr;
855         int transp, new_transp, orig_transp;
856         int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
857
858         matnr = -1;
859         smoothnormal = 0;
860         dodraw = 0;
861         transp = GPU_get_material_blend_mode();
862         orig_transp = transp;
863
864         glShadeModel(GL_SMOOTH);
865
866         if( GPU_buffer_legacy(dm) || setDrawOptions != 0 ) {
867                 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
868                 memset(&attribs, 0, sizeof(attribs));
869
870                 glBegin(GL_QUADS);
871
872                 for(a = 0; a < dm->numFaceData; a++, mface++) {
873                         new_matnr = mface->mat_nr + 1;
874
875                         if(new_matnr != matnr) {
876                                 glEnd();
877
878                                 dodraw = setMaterial(matnr = new_matnr, &gattribs);
879                                 if(dodraw)
880                                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
881
882                                 glBegin(GL_QUADS);
883                         }
884
885                         if(!dodraw) {
886                                 continue;
887                         }
888                         else if(setDrawOptions) {
889                                 orig = index[a];
890
891                                 if(orig == ORIGINDEX_NONE)
892                                         continue;
893                                 else if(!setDrawOptions(userData, orig))
894                                         continue;
895                         }
896
897                         if(tf) {
898                                 new_transp = tf[a].transp;
899
900                                 if(new_transp != transp) {
901                                         glEnd();
902
903                                         if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
904                                                 GPU_set_material_blend_mode(orig_transp);
905                                         else
906                                                 GPU_set_material_blend_mode(new_transp);
907                                         transp = new_transp;
908
909                                         glBegin(GL_QUADS);
910                                 }
911                         }
912
913                         smoothnormal = (mface->flag & ME_SMOOTH);
914
915                         if(!smoothnormal) {
916                                 if(nors) {
917                                         glNormal3fv(nors[a]);
918                                 }
919                                 else {
920                                         /* TODO ideally a normal layer should always be available */
921                                         float nor[3];
922                                         if(mface->v4) {
923                                                 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
924                                         } else {
925                                                 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
926                                         }
927                                         glNormal3fv(nor);
928                                 }
929                         }
930
931 #define PASSVERT(index, vert) {                                                                                                 \
932                 if(attribs.totorco)                                                                                                                     \
933                         glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]);  \
934                 for(b = 0; b < attribs.tottface; b++) {                                                                         \
935                         MTFace *tf = &attribs.tface[b].array[a];                                                                \
936                         glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);                   \
937                 }                                                                                                                                                       \
938                 for(b = 0; b < attribs.totmcol; b++) {                                                                          \
939                         MCol *cp = &attribs.mcol[b].array[a*4 + vert];                                                  \
940                         GLubyte col[4];                                                                                                                 \
941                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
942                         glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
943                 }                                                                                                                                                       \
944                 if(attribs.tottang) {                                                                                                           \
945                         float *tang = attribs.tang.array[a*4 + vert];                                                   \
946                         glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
947                 }                                                                                                                                                       \
948                 if(smoothnormal)                                                                                                                        \
949                         glNormal3sv(mvert[index].no);                                                                                   \
950                 glVertex3fv(mvert[index].co);                                                                                           \
951         }
952
953                         PASSVERT(mface->v1, 0);
954                         PASSVERT(mface->v2, 1);
955                         PASSVERT(mface->v3, 2);
956                         if(mface->v4)
957                                 PASSVERT(mface->v4, 3)
958                         else
959                                 PASSVERT(mface->v3, 2)
960
961 #undef PASSVERT
962                 }
963                 glEnd();
964         }
965         else {
966                 GPUBuffer *buffer = 0;
967                 char *varray = 0;
968                 int numdata = 0, elementsize = 0, offset;
969                 int start = 0, numfaces = 0, prevdraw = 0, curface = 0;
970                 GPUAttrib datatypes[32];
971                 memset(&attribs, 0, sizeof(attribs));
972
973                 GPU_vertex_setup(dm);
974                 GPU_normal_setup(dm);
975
976                 if( !GPU_buffer_legacy(dm) ) {
977                         for(a = 0; a < dm->numFaceData; a++, mface++) {
978                                 new_matnr = mface->mat_nr + 1;
979
980                                 if(new_matnr != matnr ) {
981                                         numfaces = curface - start;
982                                         if( numfaces > 0 ) {
983                                                 if( prevdraw ) {
984                                                         GPU_buffer_unlock(buffer);
985                                                         GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
986                                                         glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
987                                                         GPU_buffer_free(buffer,0);
988                                                 }
989                                         }
990                                         start = curface;
991                                         prevdraw = dodraw;
992                                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
993                                         if(dodraw) {
994                                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
995
996                                                 if(attribs.totorco) {
997                                                         datatypes[numdata].index = attribs.orco.glIndex;
998                                                         datatypes[numdata].size = 3;
999                                                         datatypes[numdata].type = GL_FLOAT;
1000                                                         numdata++;
1001                                                 }
1002                                                 for(b = 0; b < attribs.tottface; b++) {
1003                                                         datatypes[numdata].index = attribs.tface[b].glIndex;
1004                                                         datatypes[numdata].size = 2;
1005                                                         datatypes[numdata].type = GL_FLOAT;
1006                                                         numdata++;
1007                                                 }       
1008                                                 for(b = 0; b < attribs.totmcol; b++) {
1009                                                         datatypes[numdata].index = attribs.mcol[b].glIndex;
1010                                                         datatypes[numdata].size = 4;
1011                                                         datatypes[numdata].type = GL_UNSIGNED_BYTE;
1012                                                         numdata++;
1013                                                 }       
1014                                                 if(attribs.tottang) {
1015                                                         datatypes[numdata].index = attribs.tang.glIndex;
1016                                                         datatypes[numdata].size = 3;
1017                                                         datatypes[numdata].type = GL_FLOAT;
1018                                                         numdata++;
1019                                                 }
1020                                                 if( numdata != 0 ) {
1021                                                         elementsize = GPU_attrib_element_size( datatypes, numdata );
1022                                                         buffer = GPU_buffer_alloc( elementsize*dm->drawObject->nelements, 0 );
1023                                                         if( buffer == 0 ) {
1024                                                                 GPU_buffer_unbind();
1025                                                                 dm->drawObject->legacy = 1;
1026                                                                 return;
1027                                                         }
1028                                                         varray = GPU_buffer_lock_stream(buffer);
1029                                                         if( varray == 0 ) {
1030                                                                 GPU_buffer_unbind();
1031                                                                 GPU_buffer_free(buffer, 0);
1032                                                                 dm->drawObject->legacy = 1;
1033                                                                 return;
1034                                                         }
1035                                                 }
1036                                         }
1037                                 }
1038                                 if(!dodraw) {
1039                                         continue;
1040                                 }
1041
1042                                 if(tf) {
1043                                         new_transp = tf[a].transp;
1044
1045                                         if(new_transp != transp) {
1046                                                 numfaces = curface - start;
1047                                                 if( numfaces > 0 ) {
1048                                                         if( dodraw ) {
1049                                                                 if( numdata != 0 ) {
1050                                                                         GPU_buffer_unlock(buffer);
1051                                                                         GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1052                                                                 }
1053                                                                 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1054                                                                 if( numdata != 0 ) {
1055                                                                         varray = GPU_buffer_lock_stream(buffer);
1056                                                                 }
1057                                                         }
1058                                                 }
1059                                                 start = curface;
1060
1061                                                 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1062                                                         GPU_set_material_blend_mode(orig_transp);
1063                                                 else
1064                                                         GPU_set_material_blend_mode(new_transp);
1065                                                 transp = new_transp;
1066                                         }
1067                                 }
1068                                 
1069                                 if( numdata != 0 ) {
1070                                         offset = 0;
1071                                         if(attribs.totorco) {
1072                                                 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
1073                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
1074                                                 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
1075                                                 offset += sizeof(float)*3;
1076                                         }
1077                                         for(b = 0; b < attribs.tottface; b++) {
1078                                                 MTFace *tf = &attribs.tface[b].array[a];
1079                                                 VECCOPY((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
1080                                                 VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
1081                                                 VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
1082                                                 offset += sizeof(float)*2;
1083                                         }
1084                                         for(b = 0; b < attribs.totmcol; b++) {
1085                                                 MCol *cp = &attribs.mcol[b].array[a*4 + 0];
1086                                                 GLubyte col[4];
1087                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1088                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1089                                                 cp = &attribs.mcol[b].array[a*4 + 1];
1090                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1091                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1092                                                 cp = &attribs.mcol[b].array[a*4 + 2];
1093                                                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1094                                                 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1095                                                 offset += sizeof(unsigned char)*4;
1096                                         }       
1097                                         if(attribs.tottang) {
1098                                                 float *tang = attribs.tang.array[a*4 + 0];
1099                                                 VECCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1100                                                 tang = attribs.tang.array[a*4 + 1];
1101                                                 VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1102                                                 tang = attribs.tang.array[a*4 + 2];
1103                                                 VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1104                                                 offset += sizeof(float)*3;
1105                                         }
1106                                 }
1107                                 curface++;
1108                                 if(mface->v4) {
1109                                         if( numdata != 0 ) {
1110                                                 offset = 0;
1111                                                 if(attribs.totorco) {
1112                                                         VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1113                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1114                                                         VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1115                                                         offset += sizeof(float)*3;
1116                                                 }
1117                                                 for(b = 0; b < attribs.tottface; b++) {
1118                                                         MTFace *tf = &attribs.tface[b].array[a];
1119                                                         VECCOPY((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1120                                                         VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1121                                                         VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1122                                                         offset += sizeof(float)*2;
1123                                                 }
1124                                                 for(b = 0; b < attribs.totmcol; b++) {
1125                                                         MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1126                                                         GLubyte col[4];
1127                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1128                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1129                                                         cp = &attribs.mcol[b].array[a*4 + 3];
1130                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1131                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1132                                                         cp = &attribs.mcol[b].array[a*4 + 0];
1133                                                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1134                                                         QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1135                                                         offset += sizeof(unsigned char)*4;
1136                                                 }       
1137                                                 if(attribs.tottang) {
1138                                                         float *tang = attribs.tang.array[a*4 + 2];
1139                                                         VECCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1140                                                         tang = attribs.tang.array[a*4 + 3];
1141                                                         VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1142                                                         tang = attribs.tang.array[a*4 + 0];
1143                                                         VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1144                                                         offset += sizeof(float)*3;
1145                                                 }
1146                                         }
1147                                         curface++;
1148                                 }
1149                         }
1150                         numfaces = curface - start;
1151                         if( numfaces > 0 ) {
1152                                 if( dodraw ) {
1153                                         if( numdata != 0 ) {
1154                                                 GPU_buffer_unlock(buffer);
1155                                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1156                                         }
1157                                         glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1158                                 }
1159                         }
1160                         GPU_buffer_unbind();
1161                 }
1162                 GPU_buffer_free( buffer, 0 );
1163         }
1164
1165         glShadeModel(GL_FLAT);
1166 }
1167
1168 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
1169 {
1170         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1171 }
1172
1173 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1174 {
1175         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1176         MVert *vert = cddm->mvert;
1177         MEdge *edge = cddm->medge;
1178         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1179
1180         glBegin(GL_LINES);
1181         for(i = 0; i < dm->numEdgeData; i++, edge++) {
1182                 if(index) {
1183                         orig = *index++;
1184                         if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1185                 }
1186                 else
1187                         orig = i;
1188
1189                 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1190                         glVertex3fv(vert[edge->v1].co);
1191                         glVertex3fv(vert[edge->v2].co);
1192                 }
1193         }
1194         glEnd();
1195 }
1196
1197 static void cdDM_foreachMappedVert(
1198                            DerivedMesh *dm,
1199                            void (*func)(void *userData, int index, float *co,
1200                                         float *no_f, short *no_s),
1201                            void *userData)
1202 {
1203         MVert *mv = CDDM_get_verts(dm);
1204         int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1205
1206         for(i = 0; i < dm->numVertData; i++, mv++) {
1207                 if(index) {
1208                         orig = *index++;
1209                         if(orig == ORIGINDEX_NONE) continue;
1210                         func(userData, orig, mv->co, NULL, mv->no);
1211                 }
1212                 else
1213                         func(userData, i, mv->co, NULL, mv->no);
1214         }
1215 }
1216
1217 static void cdDM_foreachMappedEdge(
1218                            DerivedMesh *dm,
1219                            void (*func)(void *userData, int index,
1220                                         float *v0co, float *v1co),
1221                            void *userData)
1222 {
1223         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1224         MVert *mv = cddm->mvert;
1225         MEdge *med = cddm->medge;
1226         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1227
1228         for(i = 0; i < dm->numEdgeData; i++, med++) {
1229                 if (index) {
1230                         orig = *index++;
1231                         if(orig == ORIGINDEX_NONE) continue;
1232                         func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1233                 }
1234                 else
1235                         func(userData, i, mv[med->v1].co, mv[med->v2].co);
1236         }
1237 }
1238
1239 static void cdDM_foreachMappedFaceCenter(
1240                            DerivedMesh *dm,
1241                            void (*func)(void *userData, int index,
1242                                         float *cent, float *no),
1243                            void *userData)
1244 {
1245         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1246         MVert *mv = cddm->mvert;
1247         MFace *mf = cddm->mface;
1248         int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
1249
1250         for(i = 0; i < dm->numFaceData; i++, mf++) {
1251                 float cent[3];
1252                 float no[3];
1253
1254                 if (index) {
1255                         orig = *index++;
1256                         if(orig == ORIGINDEX_NONE) continue;
1257                 }
1258                 else
1259                         orig = i;
1260
1261                 VECCOPY(cent, mv[mf->v1].co);
1262                 add_v3_v3v3(cent, cent, mv[mf->v2].co);
1263                 add_v3_v3v3(cent, cent, mv[mf->v3].co);
1264
1265                 if (mf->v4) {
1266                         normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
1267                         add_v3_v3v3(cent, cent, mv[mf->v4].co);
1268                         mul_v3_fl(cent, 0.25f);
1269                 } else {
1270                         normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
1271                         mul_v3_fl(cent, 0.33333333333f);
1272                 }
1273
1274                 func(userData, orig, cent, no);
1275         }
1276 }
1277
1278 static void cdDM_release(DerivedMesh *dm)
1279 {
1280         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1281
1282         if (DM_release(dm))
1283                 MEM_freeN(cddm);
1284 }
1285
1286 /**************** CDDM interface functions ****************/
1287 static CDDerivedMesh *cdDM_create(const char *desc)
1288 {
1289         CDDerivedMesh *cddm;
1290         DerivedMesh *dm;
1291
1292         cddm = MEM_callocN(sizeof(*cddm), desc);
1293         dm = &cddm->dm;
1294
1295         dm->getMinMax = cdDM_getMinMax;
1296
1297         dm->getNumVerts = cdDM_getNumVerts;
1298         dm->getNumFaces = cdDM_getNumFaces;
1299         dm->getNumEdges = cdDM_getNumEdges;
1300
1301         dm->getVert = cdDM_getVert;
1302         dm->getEdge = cdDM_getEdge;
1303         dm->getFace = cdDM_getFace;
1304         dm->copyVertArray = cdDM_copyVertArray;
1305         dm->copyEdgeArray = cdDM_copyEdgeArray;
1306         dm->copyFaceArray = cdDM_copyFaceArray;
1307         dm->getVertData = DM_get_vert_data;
1308         dm->getEdgeData = DM_get_edge_data;
1309         dm->getFaceData = DM_get_face_data;
1310         dm->getVertDataArray = DM_get_vert_data_layer;
1311         dm->getEdgeDataArray = DM_get_edge_data_layer;
1312         dm->getFaceDataArray = DM_get_face_data_layer;
1313
1314         dm->getVertCos = cdDM_getVertCos;
1315         dm->getVertCo = cdDM_getVertCo;
1316         dm->getVertNo = cdDM_getVertNo;
1317
1318         dm->drawVerts = cdDM_drawVerts;
1319
1320         dm->drawUVEdges = cdDM_drawUVEdges;
1321         dm->drawEdges = cdDM_drawEdges;
1322         dm->drawLooseEdges = cdDM_drawLooseEdges;
1323         dm->drawMappedEdges = cdDM_drawMappedEdges;
1324
1325         dm->drawFacesSolid = cdDM_drawFacesSolid;
1326         dm->drawFacesColored = cdDM_drawFacesColored;
1327         dm->drawFacesTex = cdDM_drawFacesTex;
1328         dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1329         dm->drawMappedFaces = cdDM_drawMappedFaces;
1330         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1331         dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1332
1333         dm->foreachMappedVert = cdDM_foreachMappedVert;
1334         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1335         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1336
1337         dm->release = cdDM_release;
1338
1339         return cddm;
1340 }
1341
1342 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
1343 {
1344         CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1345         DerivedMesh *dm = &cddm->dm;
1346
1347         DM_init(dm, numVerts, numEdges, numFaces);
1348
1349         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1350         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1351         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1352
1353         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1354         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1355         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1356
1357         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1358         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1359         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1360
1361         return dm;
1362 }
1363
1364 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
1365 {
1366         CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1367         DerivedMesh *dm = &cddm->dm;
1368         CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1369         int i, *index, alloctype;
1370
1371         /* this does a referenced copy, the only new layers being ORIGINDEX,
1372          * with an exception for fluidsim */
1373
1374         DM_init(dm, mesh->totvert, mesh->totedge, mesh->totface);
1375
1376         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totvert);
1377         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totedge);
1378         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface);
1379
1380         dm->deformedOnly = 1;
1381
1382         alloctype= CD_REFERENCE;
1383
1384         CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1385                          mesh->totvert);
1386         CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1387                          mesh->totedge);
1388         CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
1389                          mesh->totface);
1390
1391         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1392         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1393         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1394
1395         index = CustomData_get_layer(&dm->vertData, CD_ORIGINDEX);
1396         for(i = 0; i < mesh->totvert; ++i, ++index)
1397                 *index = i;
1398
1399         index = CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX);
1400         for(i = 0; i < mesh->totedge; ++i, ++index)
1401                 *index = i;
1402
1403         index = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX);
1404         for(i = 0; i < mesh->totface; ++i, ++index)
1405                 *index = i;
1406
1407         return dm;
1408 }
1409
1410 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
1411 {
1412         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1413                                    BLI_countlist(&em->edges),
1414                                    BLI_countlist(&em->faces));
1415         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1416         EditVert *eve;
1417         EditEdge *eed;
1418         EditFace *efa;
1419         MVert *mvert = cddm->mvert;
1420         MEdge *medge = cddm->medge;
1421         MFace *mface = cddm->mface;
1422         int i, *index;
1423
1424         dm->deformedOnly = 1;
1425
1426         CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1427                          CD_CALLOC, dm->numVertData);
1428         /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1429                          CD_CALLOC, dm->numEdgeData); */
1430         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1431                          CD_CALLOC, dm->numFaceData);
1432
1433         /* set eve->hash to vert index */
1434         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1435                 eve->tmp.l = i;
1436
1437         /* Need to be able to mark loose edges */
1438         for(eed = em->edges.first; eed; eed = eed->next) {
1439                 eed->f2 = 0;
1440         }
1441         for(efa = em->faces.first; efa; efa = efa->next) {
1442                 efa->e1->f2 = 1;
1443                 efa->e2->f2 = 1;
1444                 efa->e3->f2 = 1;
1445                 if(efa->e4) efa->e4->f2 = 1;
1446         }
1447
1448         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1449         for(i = 0, eve = em->verts.first; i < dm->numVertData;
1450             i++, eve = eve->next, index++) {
1451                 MVert *mv = &mvert[i];
1452
1453                 VECCOPY(mv->co, eve->co);
1454
1455                 mv->no[0] = eve->no[0] * 32767.0;
1456                 mv->no[1] = eve->no[1] * 32767.0;
1457                 mv->no[2] = eve->no[2] * 32767.0;
1458                 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1459
1460                 mv->mat_nr = 0;
1461                 mv->flag = 0;
1462
1463                 *index = i;
1464
1465                 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1466         }
1467
1468         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1469         for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1470             i++, eed = eed->next, index++) {
1471                 MEdge *med = &medge[i];
1472
1473                 med->v1 = eed->v1->tmp.l;
1474                 med->v2 = eed->v2->tmp.l;
1475                 med->crease = (unsigned char) (eed->crease * 255.0f);
1476                 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1477                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1478                 
1479                 if(eed->seam) med->flag |= ME_SEAM;
1480                 if(eed->sharp) med->flag |= ME_SHARP;
1481                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1482
1483                 *index = i;
1484
1485                 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1486         }
1487
1488         index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
1489         for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1490             i++, efa = efa->next, index++) {
1491                 MFace *mf = &mface[i];
1492
1493                 mf->v1 = efa->v1->tmp.l;
1494                 mf->v2 = efa->v2->tmp.l;
1495                 mf->v3 = efa->v3->tmp.l;
1496                 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1497                 mf->mat_nr = efa->mat_nr;
1498                 mf->flag = efa->flag;
1499
1500                 *index = i;
1501
1502                 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1503                 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1504         }
1505
1506         return dm;
1507 }
1508
1509 DerivedMesh *CDDM_copy(DerivedMesh *source)
1510 {
1511         CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
1512         DerivedMesh *dm = &cddm->dm;
1513         int numVerts = source->numVertData;
1514         int numEdges = source->numEdgeData;
1515         int numFaces = source->numFaceData;
1516
1517         /* this initializes dm, and copies all non mvert/medge/mface layers */
1518         DM_from_template(dm, source, numVerts, numEdges, numFaces);
1519         dm->deformedOnly = source->deformedOnly;
1520
1521         CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
1522         CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
1523         CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
1524
1525         /* now add mvert/medge/mface layers */
1526         cddm->mvert = source->dupVertArray(source);
1527         cddm->medge = source->dupEdgeArray(source);
1528         cddm->mface = source->dupFaceArray(source);
1529
1530         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
1531         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
1532         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
1533
1534         return dm;
1535 }
1536
1537 DerivedMesh *CDDM_from_template(DerivedMesh *source,
1538                                 int numVerts, int numEdges, int numFaces)
1539 {
1540         CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
1541         DerivedMesh *dm = &cddm->dm;
1542
1543         /* this does a copy of all non mvert/medge/mface layers */
1544         DM_from_template(dm, source, numVerts, numEdges, numFaces);
1545
1546         /* now add mvert/medge/mface layers */
1547         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1548         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1549         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1550
1551         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1552         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1553         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1554
1555         return dm;
1556 }
1557
1558 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
1559 {
1560         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1561         MVert *vert;
1562         int i;
1563
1564         /* this will just return the pointer if it wasn't a referenced layer */
1565         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1566         cddm->mvert = vert;
1567
1568         for(i = 0; i < dm->numVertData; ++i, ++vert)
1569                 VECCOPY(vert->co, vertCoords[i]);
1570 }
1571
1572 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
1573 {
1574         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1575         MVert *vert;
1576         int i;
1577
1578         /* this will just return the pointer if it wasn't a referenced layer */
1579         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1580         cddm->mvert = vert;
1581
1582         for(i = 0; i < dm->numVertData; ++i, ++vert)
1583                 VECCOPY(vert->no, vertNormals[i]);
1584 }
1585
1586 /* adapted from mesh_calc_normals */
1587 void CDDM_calc_normals(DerivedMesh *dm)
1588 {
1589         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1590         float (*temp_nors)[3];
1591         float (*face_nors)[3];
1592         int i;
1593         int numVerts = dm->numVertData;
1594         int numFaces = dm->numFaceData;
1595         MFace *mf;
1596         MVert *mv;
1597
1598         if(numVerts == 0) return;
1599
1600         temp_nors = MEM_callocN(numVerts * sizeof(*temp_nors),
1601                                 "CDDM_calc_normals temp_nors");
1602
1603         /* we don't want to overwrite any referenced layers */
1604         mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1605         cddm->mvert = mv;
1606
1607         /* make a face normal layer if not present */
1608         face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
1609         if(!face_nors)
1610                 face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
1611                                                  NULL, dm->numFaceData);
1612
1613         /* calculate face normals and add to vertex normals */
1614         mf = CDDM_get_faces(dm);
1615         for(i = 0; i < numFaces; i++, mf++) {
1616                 float *f_no = face_nors[i];
1617
1618                 if(mf->v4)
1619                         normal_quad_v3( f_no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
1620                 else
1621                         normal_tri_v3( f_no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
1622                 
1623                 add_v3_v3v3(temp_nors[mf->v1], temp_nors[mf->v1], f_no);
1624                 add_v3_v3v3(temp_nors[mf->v2], temp_nors[mf->v2], f_no);
1625                 add_v3_v3v3(temp_nors[mf->v3], temp_nors[mf->v3], f_no);
1626                 if(mf->v4)
1627                         add_v3_v3v3(temp_nors[mf->v4], temp_nors[mf->v4], f_no);
1628         }
1629
1630         /* normalize vertex normals and assign */
1631         for(i = 0; i < numVerts; i++, mv++) {
1632                 float *no = temp_nors[i];
1633                 
1634                 if (normalize_v3(no) == 0.0) {
1635                         VECCOPY(no, mv->co);
1636                         normalize_v3(no);
1637                 }
1638
1639                 mv->no[0] = (short)(no[0] * 32767.0);
1640                 mv->no[1] = (short)(no[1] * 32767.0);
1641                 mv->no[2] = (short)(no[2] * 32767.0);
1642         }
1643         
1644         MEM_freeN(temp_nors);
1645 }
1646
1647 void CDDM_calc_edges(DerivedMesh *dm)
1648 {
1649         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1650         CustomData edgeData;
1651         EdgeHashIterator *ehi;
1652         MFace *mf = cddm->mface;
1653         MEdge *med;
1654         EdgeHash *eh = BLI_edgehash_new();
1655         int i, *index, numEdges, maxFaces = dm->numFaceData;
1656
1657         for (i = 0; i < maxFaces; i++, mf++) {
1658                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
1659                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
1660                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
1661                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
1662                 
1663                 if (mf->v4) {
1664                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
1665                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
1666                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
1667                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
1668                 } else {
1669                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
1670                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
1671                 }
1672         }
1673
1674         numEdges = BLI_edgehash_size(eh);
1675
1676         /* write new edges into a temporary CustomData */
1677         memset(&edgeData, 0, sizeof(edgeData));
1678         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1679         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1680
1681         ehi = BLI_edgehashIterator_new(eh);
1682         med = CustomData_get_layer(&edgeData, CD_MEDGE);
1683         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
1684         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
1685             BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
1686                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
1687
1688                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1689                 *index = ORIGINDEX_NONE;
1690         }
1691         BLI_edgehashIterator_free(ehi);
1692
1693         /* free old CustomData and assign new one */
1694         CustomData_free(&dm->edgeData, dm->numEdgeData);
1695         dm->edgeData = edgeData;
1696         dm->numEdgeData = numEdges;
1697
1698         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1699
1700         BLI_edgehash_free(eh, NULL);
1701 }
1702
1703 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
1704 {
1705         if (numVerts < dm->numVertData)
1706                 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
1707
1708         dm->numVertData = numVerts;
1709 }
1710
1711 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
1712 {
1713         if (numEdges < dm->numEdgeData)
1714                 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
1715
1716         dm->numEdgeData = numEdges;
1717 }
1718
1719 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
1720 {
1721         if (numFaces < dm->numFaceData)
1722                 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
1723
1724         dm->numFaceData = numFaces;
1725 }
1726
1727 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
1728 {
1729         return &((CDDerivedMesh*)dm)->mvert[index];
1730 }
1731
1732 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
1733 {
1734         return &((CDDerivedMesh*)dm)->medge[index];
1735 }
1736
1737 MFace *CDDM_get_face(DerivedMesh *dm, int index)
1738 {
1739         return &((CDDerivedMesh*)dm)->mface[index];
1740 }
1741
1742 MVert *CDDM_get_verts(DerivedMesh *dm)
1743 {
1744         return ((CDDerivedMesh*)dm)->mvert;
1745 }
1746
1747 MEdge *CDDM_get_edges(DerivedMesh *dm)
1748 {
1749         return ((CDDerivedMesh*)dm)->medge;
1750 }
1751
1752 MFace *CDDM_get_faces(DerivedMesh *dm)
1753 {
1754         return ((CDDerivedMesh*)dm)->mface;
1755 }
1756
1757 /* Multires DerivedMesh, extends CDDM */
1758 typedef struct MultiresDM {
1759         CDDerivedMesh cddm;
1760
1761         MultiresModifierData *mmd;
1762         int local_mmd;
1763
1764         int lvl, totlvl;
1765         float (*orco)[3];
1766         MVert *subco;
1767
1768         ListBase *vert_face_map, *vert_edge_map;
1769         IndexNode *vert_face_map_mem, *vert_edge_map_mem;
1770         int *face_offsets;
1771
1772         Object *ob;
1773         int modified;
1774
1775         void (*update)(DerivedMesh*);
1776 } MultiresDM;
1777
1778 static void MultiresDM_release(DerivedMesh *dm)
1779 {
1780         MultiresDM *mrdm = (MultiresDM*)dm;
1781         int mvert_layer;
1782
1783         /* Before freeing, need to update the displacement map */
1784         if(dm->needsFree && mrdm->modified) {
1785                 /* Check that mmd still exists */
1786                 if(!mrdm->local_mmd && BLI_findindex(&mrdm->ob->modifiers, mrdm->mmd) < 0)
1787                         mrdm->mmd = NULL;
1788                 if(mrdm->mmd)
1789                         mrdm->update(dm);
1790         }
1791
1792         /* If the MVert data is being used as the sculpt undo store, don't free it */
1793         mvert_layer = CustomData_get_layer_index(&dm->vertData, CD_MVERT);
1794         if(mvert_layer != -1) {
1795                 CustomDataLayer *cd = &dm->vertData.layers[mvert_layer];
1796                 if(mrdm->mmd && cd->data == mrdm->mmd->undo_verts)
1797                         cd->flag |= CD_FLAG_NOFREE;
1798         }
1799
1800         if(DM_release(dm)) {
1801                 MEM_freeN(mrdm->subco);
1802                 MEM_freeN(mrdm->orco);
1803                 if(mrdm->vert_face_map)
1804                         MEM_freeN(mrdm->vert_face_map);
1805                 if(mrdm->vert_face_map_mem)
1806                         MEM_freeN(mrdm->vert_face_map_mem);
1807                 if(mrdm->vert_edge_map)
1808                         MEM_freeN(mrdm->vert_edge_map);
1809                 if(mrdm->vert_edge_map_mem)
1810                         MEM_freeN(mrdm->vert_edge_map_mem);
1811                 if(mrdm->face_offsets)
1812                         MEM_freeN(mrdm->face_offsets);
1813                 MEM_freeN(mrdm);
1814         }
1815 }
1816
1817 DerivedMesh *MultiresDM_new(MultiresSubsurf *ms, DerivedMesh *orig, int numVerts, int numEdges, int numFaces)
1818 {
1819         MultiresDM *mrdm = MEM_callocN(sizeof(MultiresDM), "MultiresDM");
1820         CDDerivedMesh *cddm = cdDM_create("MultiresDM CDDM");
1821         DerivedMesh *dm = NULL;
1822
1823         mrdm->cddm = *cddm;
1824         MEM_freeN(cddm);
1825         dm = &mrdm->cddm.dm;
1826
1827         mrdm->mmd = ms->mmd;
1828         mrdm->ob = ms->ob;
1829         mrdm->local_mmd = ms->local_mmd;
1830
1831         if(dm) {
1832                 MDisps *disps;
1833                 MVert *mvert;
1834                 int i;
1835
1836                 DM_from_template(dm, orig, numVerts, numEdges, numFaces);
1837                 CustomData_free_layers(&dm->faceData, CD_MDISPS, numFaces);
1838
1839                 disps = CustomData_get_layer(&orig->faceData, CD_MDISPS);
1840                 if(disps)
1841                         CustomData_add_layer(&dm->faceData, CD_MDISPS, CD_REFERENCE, disps, numFaces);
1842
1843
1844                 mvert = CustomData_get_layer(&orig->vertData, CD_MVERT);
1845                 mrdm->orco = MEM_callocN(sizeof(float) * 3 * orig->getNumVerts(orig), "multires orco");
1846                 for(i = 0; i < orig->getNumVerts(orig); ++i)
1847                         copy_v3_v3(mrdm->orco[i], mvert[i].co);
1848         }
1849         else
1850                 DM_init(dm, numVerts, numEdges, numFaces);
1851
1852         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1853         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1854         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1855
1856         mrdm->cddm.mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1857         mrdm->cddm.medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1858         mrdm->cddm.mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1859
1860         mrdm->lvl = ms->mmd->lvl;
1861         mrdm->totlvl = ms->mmd->totlvl;
1862         mrdm->subco = MEM_callocN(sizeof(MVert)*numVerts, "multires subdivided verts");
1863         mrdm->modified = 0;
1864
1865         dm->release = MultiresDM_release;
1866
1867         return dm;
1868 }
1869
1870 Mesh *MultiresDM_get_mesh(DerivedMesh *dm)
1871 {
1872         return get_mesh(((MultiresDM*)dm)->ob);
1873 }
1874
1875 Object *MultiresDM_get_object(DerivedMesh *dm)
1876 {
1877         return ((MultiresDM*)dm)->ob;
1878 }
1879
1880 void *MultiresDM_get_orco(DerivedMesh *dm)
1881 {
1882         return ((MultiresDM*)dm)->orco;
1883
1884 }
1885
1886 MVert *MultiresDM_get_subco(DerivedMesh *dm)
1887 {
1888         return ((MultiresDM*)dm)->subco;
1889 }
1890
1891 int MultiresDM_get_totlvl(DerivedMesh *dm)
1892 {
1893         return ((MultiresDM*)dm)->totlvl;
1894 }
1895
1896 int MultiresDM_get_lvl(DerivedMesh *dm)
1897 {
1898         return ((MultiresDM*)dm)->lvl;
1899 }
1900
1901 void MultiresDM_set_orco(DerivedMesh *dm, float (*orco)[3])
1902 {
1903         ((MultiresDM*)dm)->orco = orco;
1904 }
1905
1906 void MultiresDM_set_update(DerivedMesh *dm, void (*update)(DerivedMesh*))
1907 {
1908         ((MultiresDM*)dm)->update = update;
1909 }
1910
1911 ListBase *MultiresDM_get_vert_face_map(DerivedMesh *dm)
1912 {
1913         MultiresDM *mrdm = (MultiresDM*)dm;
1914         Mesh *me = mrdm->ob->data;
1915
1916         if(!mrdm->vert_face_map)
1917                 create_vert_face_map(&mrdm->vert_face_map, &mrdm->vert_face_map_mem, me->mface,
1918                                      me->totvert, me->totface);
1919
1920         return mrdm->vert_face_map;
1921 }
1922
1923 ListBase *MultiresDM_get_vert_edge_map(DerivedMesh *dm)
1924 {
1925         MultiresDM *mrdm = (MultiresDM*)dm;
1926         Mesh *me = mrdm->ob->data;
1927
1928         if(!mrdm->vert_edge_map)
1929                 create_vert_edge_map(&mrdm->vert_edge_map, &mrdm->vert_edge_map_mem, me->medge,
1930                                      me->totvert, me->totedge);
1931
1932         return mrdm->vert_edge_map;
1933 }
1934
1935 int *MultiresDM_get_face_offsets(DerivedMesh *dm)
1936 {
1937         MultiresDM *mrdm = (MultiresDM*)dm;
1938         Mesh *me = mrdm->ob->data;
1939         int i, accum = 0;
1940
1941         if(!mrdm->face_offsets) {
1942                 int len = (int)pow(2, mrdm->lvl - 2) - 1;
1943                 int area = len * len;
1944                 int t = 1 + len * 3 + area * 3, q = t + len + area;
1945
1946                 mrdm->face_offsets = MEM_callocN(sizeof(int) * me->totface, "mrdm face offsets");
1947                 for(i = 0; i < me->totface; ++i) {
1948                         mrdm->face_offsets[i] = accum;
1949
1950                         accum += (me->mface[i].v4 ? q : t);
1951                 }
1952         }
1953
1954         return mrdm->face_offsets;
1955 }
1956
1957 void MultiresDM_mark_as_modified(DerivedMesh *dm)
1958 {
1959         ((MultiresDM*)dm)->modified = 1;
1960 }