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