Merge from trunk
[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_utildefines.h"
46
47 #include "BLI_arithb.h"
48 #include "BLI_blenlib.h"
49 #include "BLI_edgehash.h"
50 #include "BLI_editVert.h"
51 #include "BLI_ghash.h"
52
53 #include "DNA_mesh_types.h"
54 #include "DNA_meshdata_types.h"
55 #include "DNA_object_fluidsim.h"
56 #include "DNA_object_types.h"
57 #include "DNA_scene_types.h"
58
59 #include "MEM_guardedalloc.h"
60
61 #include "GPU_draw.h"
62 #include "GPU_extensions.h"
63 #include "GPU_material.h"
64
65 #include <string.h>
66 #include <limits.h>
67
68 typedef struct {
69         DerivedMesh dm;
70
71         /* these point to data in the DerivedMesh custom data layers,
72            they are only here for efficiency and convenience **/
73         MVert *mvert;
74         MEdge *medge;
75         MFace *mface;
76 } CDDerivedMesh;
77
78 /**************** DerivedMesh interface functions ****************/
79 static int cdDM_getNumVerts(DerivedMesh *dm)
80 {
81         return dm->numVertData;
82 }
83
84 static int cdDM_getNumEdges(DerivedMesh *dm)
85 {
86         return dm->numEdgeData;
87 }
88
89 static int cdDM_getNumFaces(DerivedMesh *dm)
90 {
91         return dm->numFaceData;
92 }
93
94 static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
95 {
96         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
97         *vert_r = cddm->mvert[index];
98 }
99
100 static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
101 {
102         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
103         *edge_r = cddm->medge[index];
104 }
105
106 static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
107 {
108         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
109         *face_r = cddm->mface[index];
110 }
111
112 static void cdDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
113 {
114         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
115         memcpy(vert_r, cddm->mvert, sizeof(*vert_r) * dm->numVertData);
116 }
117
118 static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
119 {
120         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
121         memcpy(edge_r, cddm->medge, sizeof(*edge_r) * dm->numEdgeData);
122 }
123
124 void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
125 {
126         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
127         memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData);
128 }
129
130 static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
131 {
132         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
133         int i;
134
135         if (dm->numVertData) {
136                 for (i=0; i<dm->numVertData; i++) {
137                         DO_MINMAX(cddm->mvert[i].co, min_r, max_r);
138                 }
139         } else {
140                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
141         }
142 }
143
144 static void cdDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
145 {
146         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
147
148         VECCOPY(co_r, cddm->mvert[index].co);
149 }
150
151 static void cdDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
152 {
153         MVert *mv = CDDM_get_verts(dm);
154         int i;
155
156         for(i = 0; i < dm->numVertData; i++, mv++)
157                 VECCOPY(cos_r[i], mv->co);
158 }
159
160 static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
161 {
162         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
163         short *no = cddm->mvert[index].no;
164
165         no_r[0] = no[0]/32767.f;
166         no_r[1] = no[1]/32767.f;
167         no_r[2] = no[2]/32767.f;
168 }
169
170 static void cdDM_drawVerts(DerivedMesh *dm)
171 {
172         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
173         MVert *mv = cddm->mvert;
174         int i;
175
176         glBegin(GL_POINTS);
177         for(i = 0; i < dm->numVertData; i++, mv++)
178                 glVertex3fv(mv->co);
179         glEnd();
180 }
181
182 static void cdDM_drawUVEdges(DerivedMesh *dm)
183 {
184         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
185         MFace *mf = cddm->mface;
186         MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
187         int i;
188
189         if(mf) {
190                 glBegin(GL_LINES);
191                 for(i = 0; i < dm->numFaceData; i++, mf++, tf++) {
192                         if(!(mf->flag&ME_HIDE)) {
193                                 glVertex2fv(tf->uv[0]);
194                                 glVertex2fv(tf->uv[1]);
195
196                                 glVertex2fv(tf->uv[1]);
197                                 glVertex2fv(tf->uv[2]);
198
199                                 if(!mf->v4) {
200                                         glVertex2fv(tf->uv[2]);
201                                         glVertex2fv(tf->uv[0]);
202                                 } else {
203                                         glVertex2fv(tf->uv[2]);
204                                         glVertex2fv(tf->uv[3]);
205
206                                         glVertex2fv(tf->uv[3]);
207                                         glVertex2fv(tf->uv[0]);
208                                 }
209                         }
210                 }
211                 glEnd();
212         }
213 }
214
215 static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
216 {
217         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
218         MVert *mvert = cddm->mvert;
219         MEdge *medge = cddm->medge;
220         int i;
221                 
222         glBegin(GL_LINES);
223         for(i = 0; i < dm->numEdgeData; i++, medge++) {
224                 if((medge->flag&ME_EDGEDRAW)
225                    && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
226                         glVertex3fv(mvert[medge->v1].co);
227                         glVertex3fv(mvert[medge->v2].co);
228                 }
229         }
230         glEnd();
231 }
232
233 static void cdDM_drawLooseEdges(DerivedMesh *dm)
234 {
235         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
236         MVert *mvert = cddm->mvert;
237         MEdge *medge = cddm->medge;
238         int i;
239
240         glBegin(GL_LINES);
241         for(i = 0; i < dm->numEdgeData; i++, medge++) {
242                 if(medge->flag&ME_LOOSEEDGE) {
243                         glVertex3fv(mvert[medge->v1].co);
244                         glVertex3fv(mvert[medge->v2].co);
245                 }
246         }
247         glEnd();
248 }
249
250 static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
251 {
252         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
253         MVert *mvert = cddm->mvert;
254         MFace *mface = cddm->mface;
255         float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
256         int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
257
258 #define PASSVERT(index) {                                               \
259         if(shademodel == GL_SMOOTH) {                           \
260                 short *no = mvert[index].no;                    \
261                 glNormal3sv(no);                                                \
262         }                                                                                       \
263         glVertex3fv(mvert[index].co);   \
264 }
265
266         glBegin(glmode = GL_QUADS);
267         for(a = 0; a < dm->numFaceData; a++, mface++) {
268                 int new_glmode, new_matnr, new_shademodel;
269
270                 new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
271                 new_matnr = mface->mat_nr + 1;
272                 new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
273                 
274                 if(new_glmode != glmode || new_matnr != matnr
275                    || new_shademodel != shademodel) {
276                         glEnd();
277
278                         drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
279
280                         glShadeModel(shademodel = new_shademodel);
281                         glBegin(glmode = new_glmode);
282                 } 
283                 
284                 if(drawCurrentMat) {
285                         if(shademodel == GL_FLAT) {
286                                 if (nors) {
287                                         glNormal3fv(nors);
288                                 }
289                                 else {
290                                         /* TODO make this better (cache facenormals as layer?) */
291                                         float nor[3];
292                                         if(mface->v4) {
293                                                 CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co,
294                                                                            mvert[mface->v3].co, mvert[mface->v4].co,
295                                                                            nor);
296                                         } else {
297                                                 CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co,
298                                                                           mvert[mface->v3].co, nor);
299                                         }
300                                         glNormal3fv(nor);
301                                 }
302                         }
303
304                         PASSVERT(mface->v1);
305                         PASSVERT(mface->v2);
306                         PASSVERT(mface->v3);
307                         if(mface->v4) {
308                                 PASSVERT(mface->v4);
309                         }
310                 }
311
312                 if(nors) nors += 3;
313         }
314         glEnd();
315
316         glShadeModel(GL_FLAT);
317 #undef PASSVERT
318 }
319
320 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
321 {
322         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
323         int a, glmode;
324         unsigned char *cp1, *cp2;
325         MVert *mvert = cddm->mvert;
326         MFace *mface = cddm->mface;
327
328         cp1 = col1;
329         if(col2) {
330                 cp2 = col2;
331         } else {
332                 cp2 = NULL;
333                 useTwoSided = 0;
334         }
335
336         /* there's a conflict here... twosided colors versus culling...? */
337         /* defined by history, only texture faces have culling option */
338         /* we need that as mesh option builtin, next to double sided lighting */
339         if(col1 && col2)
340                 glEnable(GL_CULL_FACE);
341         
342         glShadeModel(GL_SMOOTH);
343         glBegin(glmode = GL_QUADS);
344         for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
345                 int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
346
347                 if(new_glmode != glmode) {
348                         glEnd();
349                         glBegin(glmode = new_glmode);
350                 }
351                         
352                 glColor3ub(cp1[0], cp1[1], cp1[2]);
353                 glVertex3fv(mvert[mface->v1].co);
354                 glColor3ub(cp1[4], cp1[5], cp1[6]);
355                 glVertex3fv(mvert[mface->v2].co);
356                 glColor3ub(cp1[8], cp1[9], cp1[10]);
357                 glVertex3fv(mvert[mface->v3].co);
358                 if(mface->v4) {
359                         glColor3ub(cp1[12], cp1[13], cp1[14]);
360                         glVertex3fv(mvert[mface->v4].co);
361                 }
362                         
363                 if(useTwoSided) {
364                         glColor3ub(cp2[8], cp2[9], cp2[10]);
365                         glVertex3fv(mvert[mface->v3].co );
366                         glColor3ub(cp2[4], cp2[5], cp2[6]);
367                         glVertex3fv(mvert[mface->v2].co );
368                         glColor3ub(cp2[0], cp2[1], cp2[2]);
369                         glVertex3fv(mvert[mface->v1].co );
370                         if(mface->v4) {
371                                 glColor3ub(cp2[12], cp2[13], cp2[14]);
372                                 glVertex3fv(mvert[mface->v4].co );
373                         }
374                 }
375                 if(col2) cp2 += 16;
376         }
377         glEnd();
378
379         glShadeModel(GL_FLAT);
380         glDisable(GL_CULL_FACE);
381 }
382
383 static void cdDM_drawFacesTex_common(DerivedMesh *dm,
384                int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
385                int (*drawParamsMapped)(void *userData, int index),
386                void *userData) 
387 {
388         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
389         MVert *mv = cddm->mvert;
390         MFace *mf = cddm->mface;
391         MCol *mcol = dm->getFaceDataArray(dm, CD_MCOL);
392         float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
393         MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
394         int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
395
396         for(i = 0; i < dm->numFaceData; i++, mf++) {
397                 MVert *mvert;
398                 int flag;
399                 unsigned char *cp = NULL;
400
401                 if(drawParams) {
402                         flag = drawParams(tf? &tf[i]: NULL, mcol? &mcol[i*4]: NULL, mf->mat_nr);
403                 }
404                 else {
405                         if(index) {
406                                 orig = *index++;
407                                 if(orig == ORIGINDEX_NONE)              { if(nors) nors += 3; continue; }
408                                 if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
409                                 else    { if(nors) nors += 3; continue; }
410                         }
411                         else
412                                 if(drawParamsMapped) flag = drawParamsMapped(userData, i);
413                                 else    { if(nors) nors += 3; continue; }
414                 }
415                 
416                 if(flag != 0) { /* if the flag is 0 it means the face is hidden or invisible */
417                         if (flag==1 && mcol)
418                                 cp= (unsigned char*) &mcol[i*4];
419
420                         if(!(mf->flag&ME_SMOOTH)) {
421                                 if (nors) {
422                                         glNormal3fv(nors);
423                                 }
424                                 else {
425                                         /* TODO make this better (cache facenormals as layer?) */
426                                         float nor[3];
427                                         if(mf->v4) {
428                                                 CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
429                                                                            mv[mf->v3].co, mv[mf->v4].co,
430                                                                            nor);
431                                         } else {
432                                                 CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
433                                                                           mv[mf->v3].co, nor);
434                                         }
435                                         glNormal3fv(nor);
436                                 }
437                         }
438
439                         glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
440                         if(tf) glTexCoord2fv(tf[i].uv[0]);
441                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
442                         mvert = &mv[mf->v1];
443                         if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
444                         glVertex3fv(mvert->co);
445                                 
446                         if(tf) glTexCoord2fv(tf[i].uv[1]);
447                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
448                         mvert = &mv[mf->v2];
449                         if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
450                         glVertex3fv(mvert->co);
451
452                         if(tf) glTexCoord2fv(tf[i].uv[2]);
453                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
454                         mvert = &mv[mf->v3];
455                         if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
456                         glVertex3fv(mvert->co);
457
458                         if(mf->v4) {
459                                 if(tf) glTexCoord2fv(tf[i].uv[3]);
460                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
461                                 mvert = &mv[mf->v4];
462                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
463                                 glVertex3fv(mvert->co);
464                         }
465                         glEnd();
466                 }
467                 
468                 if(nors) nors += 3;
469         }
470 }
471
472 static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
473 {
474         cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
475 }
476
477 static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
478 {
479         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
480         MVert *mv = cddm->mvert;
481         MFace *mf = cddm->mface;
482         MCol *mc = DM_get_face_data_layer(dm, CD_MCOL);
483         float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
484         int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
485
486         for(i = 0; i < dm->numFaceData; i++, mf++) {
487                 int drawSmooth = (mf->flag & ME_SMOOTH);
488
489                 if(index) {
490                         orig = *index++;
491                         if(setDrawOptions && orig == ORIGINDEX_NONE)
492                                 { if(nors) nors += 3; continue; }
493                 }
494                 else
495                         orig = i;
496
497                 if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) {
498                         unsigned char *cp = NULL;
499
500                         if(useColors && mc)
501                                 cp = (unsigned char *)&mc[i * 4];
502
503                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
504                         glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
505
506                         if (!drawSmooth) {
507                                 if (nors) {
508                                         glNormal3fv(nors);
509                                 }
510                                 else {
511                                         /* TODO make this better (cache facenormals as layer?) */
512                                         float nor[3];
513                                         if(mf->v4) {
514                                                 CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
515                                                                            mv[mf->v3].co, mv[mf->v4].co,
516                                                                            nor);
517                                         } else {
518                                                 CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
519                                                                           mv[mf->v3].co, nor);
520                                         }
521                                         glNormal3fv(nor);
522                                 }
523
524                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
525                                 glVertex3fv(mv[mf->v1].co);
526                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
527                                 glVertex3fv(mv[mf->v2].co);
528                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
529                                 glVertex3fv(mv[mf->v3].co);
530                                 if(mf->v4) {
531                                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
532                                         glVertex3fv(mv[mf->v4].co);
533                                 }
534                         } else {
535                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
536                                 glNormal3sv(mv[mf->v1].no);
537                                 glVertex3fv(mv[mf->v1].co);
538                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
539                                 glNormal3sv(mv[mf->v2].no);
540                                 glVertex3fv(mv[mf->v2].co);
541                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
542                                 glNormal3sv(mv[mf->v3].no);
543                                 glVertex3fv(mv[mf->v3].co);
544                                 if(mf->v4) {
545                                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
546                                         glNormal3sv(mv[mf->v4].no);
547                                         glVertex3fv(mv[mf->v4].co);
548                                 }
549                         }
550
551                         glEnd();
552                 }
553                 
554                 if (nors) nors += 3;
555         }
556 }
557
558 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
559 {
560         cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
561 }
562
563 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
564 {
565         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
566         GPUVertexAttribs gattribs;
567         DMVertexAttribs attribs;
568         MVert *mvert = cddm->mvert;
569         MFace *mface = cddm->mface;
570         MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
571         float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
572         int a, b, dodraw, smoothnormal, matnr, new_matnr;
573         int transp, new_transp, orig_transp;
574         int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
575
576         matnr = -1;
577         smoothnormal = 0;
578         dodraw = 0;
579         transp = GPU_get_material_blend_mode();
580         orig_transp = transp;
581
582         memset(&attribs, 0, sizeof(attribs));
583
584         glShadeModel(GL_SMOOTH);
585         glBegin(GL_QUADS);
586
587         for(a = 0; a < dm->numFaceData; a++, mface++) {
588                 new_matnr = mface->mat_nr + 1;
589
590                 if(new_matnr != matnr) {
591                         glEnd();
592
593                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
594                         if(dodraw)
595                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
596
597                         glBegin(GL_QUADS);
598                 }
599
600                 if(!dodraw) {
601                         continue;
602                 }
603                 else if(setDrawOptions) {
604                         orig = index[a];
605
606                         if(orig == ORIGINDEX_NONE)
607                                 continue;
608                         else if(!setDrawOptions(userData, orig))
609                                 continue;
610                 }
611
612                 if(tf) {
613                         new_transp = tf[a].transp;
614
615                         if(new_transp != transp) {
616                                 glEnd();
617
618                                 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
619                                         GPU_set_material_blend_mode(orig_transp);
620                                 else
621                                         GPU_set_material_blend_mode(new_transp);
622                                 transp = new_transp;
623
624                                 glBegin(GL_QUADS);
625                         }
626                 }
627
628                 smoothnormal = (mface->flag & ME_SMOOTH);
629
630                 if(!smoothnormal) {
631                         if(nors) {
632                                 glNormal3fv(nors[a]);
633                         }
634                         else {
635                                 /* TODO ideally a normal layer should always be available */
636                                 float nor[3];
637                                 if(mface->v4) {
638                                         CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co,
639                                                                    mvert[mface->v3].co, mvert[mface->v4].co,
640                                                                    nor);
641                                 } else {
642                                         CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co,
643                                                                   mvert[mface->v3].co, nor);
644                                 }
645                                 glNormal3fv(nor);
646                         }
647                 }
648
649 #define PASSVERT(index, vert) {                                                                                                 \
650         if(attribs.totorco)                                                                                                                     \
651                 glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]);  \
652         for(b = 0; b < attribs.tottface; b++) {                                                                         \
653                 MTFace *tf = &attribs.tface[b].array[a];                                                                \
654                 glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);                   \
655         }                                                                                                                                                       \
656         for(b = 0; b < attribs.totmcol; b++) {                                                                          \
657                 MCol *cp = &attribs.mcol[b].array[a*4 + vert];                                                  \
658                 GLubyte col[4];                                                                                                                 \
659                 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
660                 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
661         }                                                                                                                                                       \
662         if(attribs.tottang) {                                                                                                           \
663                 float *tang = attribs.tang.array[a*4 + vert];                                                   \
664                 glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
665         }                                                                                                                                                       \
666         if(smoothnormal)                                                                                                                        \
667                 glNormal3sv(mvert[index].no);                                                                                   \
668         glVertex3fv(mvert[index].co);                                                                                           \
669 }
670
671                 PASSVERT(mface->v1, 0);
672                 PASSVERT(mface->v2, 1);
673                 PASSVERT(mface->v3, 2);
674                 if(mface->v4)
675                         PASSVERT(mface->v4, 3)
676                 else
677                         PASSVERT(mface->v3, 2)
678
679 #undef PASSVERT
680         }
681         glEnd();
682
683         glShadeModel(GL_FLAT);
684 }
685
686 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
687 {
688         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
689 }
690
691 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
692 {
693         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
694         MVert *vert = cddm->mvert;
695         MEdge *edge = cddm->medge;
696         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
697
698         glBegin(GL_LINES);
699         for(i = 0; i < dm->numEdgeData; i++, edge++) {
700                 if(index) {
701                         orig = *index++;
702                         if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
703                 }
704                 else
705                         orig = i;
706
707                 if(!setDrawOptions || setDrawOptions(userData, orig)) {
708                         glVertex3fv(vert[edge->v1].co);
709                         glVertex3fv(vert[edge->v2].co);
710                 }
711         }
712         glEnd();
713 }
714
715 static void cdDM_foreachMappedVert(
716                            DerivedMesh *dm,
717                            void (*func)(void *userData, int index, float *co,
718                                         float *no_f, short *no_s),
719                            void *userData)
720 {
721         MVert *mv = CDDM_get_verts(dm);
722         int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
723
724         for(i = 0; i < dm->numVertData; i++, mv++) {
725                 if(index) {
726                         orig = *index++;
727                         if(orig == ORIGINDEX_NONE) continue;
728                         func(userData, orig, mv->co, NULL, mv->no);
729                 }
730                 else
731                         func(userData, i, mv->co, NULL, mv->no);
732         }
733 }
734
735 static void cdDM_foreachMappedEdge(
736                            DerivedMesh *dm,
737                            void (*func)(void *userData, int index,
738                                         float *v0co, float *v1co),
739                            void *userData)
740 {
741         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
742         MVert *mv = cddm->mvert;
743         MEdge *med = cddm->medge;
744         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
745
746         for(i = 0; i < dm->numEdgeData; i++, med++) {
747                 if (index) {
748                         orig = *index++;
749                         if(orig == ORIGINDEX_NONE) continue;
750                         func(userData, orig, mv[med->v1].co, mv[med->v2].co);
751                 }
752                 else
753                         func(userData, i, mv[med->v1].co, mv[med->v2].co);
754         }
755 }
756
757 static void cdDM_foreachMappedFaceCenter(
758                            DerivedMesh *dm,
759                            void (*func)(void *userData, int index,
760                                         float *cent, float *no),
761                            void *userData)
762 {
763         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
764         MVert *mv = cddm->mvert;
765         MFace *mf = cddm->mface;
766         int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
767
768         for(i = 0; i < dm->numFaceData; i++, mf++) {
769                 float cent[3];
770                 float no[3];
771
772                 if (index) {
773                         orig = *index++;
774                         if(orig == ORIGINDEX_NONE) continue;
775                 }
776                 else
777                         orig = i;
778
779                 VECCOPY(cent, mv[mf->v1].co);
780                 VecAddf(cent, cent, mv[mf->v2].co);
781                 VecAddf(cent, cent, mv[mf->v3].co);
782
783                 if (mf->v4) {
784                         CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
785                                        mv[mf->v3].co, mv[mf->v4].co, no);
786                         VecAddf(cent, cent, mv[mf->v4].co);
787                         VecMulf(cent, 0.25f);
788                 } else {
789                         CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
790                                       mv[mf->v3].co, no);
791                         VecMulf(cent, 0.33333333333f);
792                 }
793
794                 func(userData, orig, cent, no);
795         }
796 }
797
798 static void cdDM_release(DerivedMesh *dm)
799 {
800         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
801
802         if (DM_release(dm))
803                 MEM_freeN(cddm);
804 }
805
806 /**************** CDDM interface functions ****************/
807 static CDDerivedMesh *cdDM_create(const char *desc)
808 {
809         CDDerivedMesh *cddm;
810         DerivedMesh *dm;
811
812         cddm = MEM_callocN(sizeof(*cddm), desc);
813         dm = &cddm->dm;
814
815         dm->getMinMax = cdDM_getMinMax;
816
817         dm->getNumVerts = cdDM_getNumVerts;
818         dm->getNumFaces = cdDM_getNumFaces;
819         dm->getNumEdges = cdDM_getNumEdges;
820
821         dm->getVert = cdDM_getVert;
822         dm->getEdge = cdDM_getEdge;
823         dm->getFace = cdDM_getFace;
824         dm->copyVertArray = cdDM_copyVertArray;
825         dm->copyEdgeArray = cdDM_copyEdgeArray;
826         dm->copyFaceArray = cdDM_copyFaceArray;
827         dm->getVertData = DM_get_vert_data;
828         dm->getEdgeData = DM_get_edge_data;
829         dm->getFaceData = DM_get_face_data;
830         dm->getVertDataArray = DM_get_vert_data_layer;
831         dm->getEdgeDataArray = DM_get_edge_data_layer;
832         dm->getFaceDataArray = DM_get_face_data_layer;
833
834         dm->getVertCos = cdDM_getVertCos;
835         dm->getVertCo = cdDM_getVertCo;
836         dm->getVertNo = cdDM_getVertNo;
837
838         dm->drawVerts = cdDM_drawVerts;
839
840         dm->drawUVEdges = cdDM_drawUVEdges;
841         dm->drawEdges = cdDM_drawEdges;
842         dm->drawLooseEdges = cdDM_drawLooseEdges;
843         dm->drawMappedEdges = cdDM_drawMappedEdges;
844
845         dm->drawFacesSolid = cdDM_drawFacesSolid;
846         dm->drawFacesColored = cdDM_drawFacesColored;
847         dm->drawFacesTex = cdDM_drawFacesTex;
848         dm->drawFacesGLSL = cdDM_drawFacesGLSL;
849         dm->drawMappedFaces = cdDM_drawMappedFaces;
850         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
851         dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
852
853         dm->foreachMappedVert = cdDM_foreachMappedVert;
854         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
855         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
856
857         dm->release = cdDM_release;
858
859         return cddm;
860 }
861
862 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
863 {
864         CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
865         DerivedMesh *dm = &cddm->dm;
866
867         DM_init(dm, numVerts, numEdges, numFaces);
868
869         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
870         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
871         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
872
873         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
874         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
875         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
876
877         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
878         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
879         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
880
881         return dm;
882 }
883
884 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
885 {
886         CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
887         DerivedMesh *dm = &cddm->dm;
888         int i, *index, alloctype;
889
890         /* this does a referenced copy, the only new layers being ORIGINDEX,
891          * with an exception for fluidsim */
892
893         DM_init(dm, mesh->totvert, mesh->totedge, mesh->totface);
894
895         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totvert);
896         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totedge);
897         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface);
898
899         dm->deformedOnly = 1;
900
901         if(ob && ob->fluidsimSettings && ob->fluidsimSettings->meshSurface)
902                 alloctype= CD_DUPLICATE;
903         else
904                 alloctype= CD_REFERENCE;
905
906         CustomData_merge(&mesh->vdata, &dm->vertData, CD_MASK_MESH, alloctype,
907                          mesh->totvert);
908         CustomData_merge(&mesh->edata, &dm->edgeData, CD_MASK_MESH, alloctype,
909                          mesh->totedge);
910         CustomData_merge(&mesh->fdata, &dm->faceData, CD_MASK_MESH, alloctype,
911                          mesh->totface);
912
913         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
914         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
915         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
916
917         index = CustomData_get_layer(&dm->vertData, CD_ORIGINDEX);
918         for(i = 0; i < mesh->totvert; ++i, ++index)
919                 *index = i;
920
921         index = CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX);
922         for(i = 0; i < mesh->totedge; ++i, ++index)
923                 *index = i;
924
925         index = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX);
926         for(i = 0; i < mesh->totface; ++i, ++index)
927                 *index = i;
928         
929         /* works in conjunction with hack during modifier calc, where active mcol
930            layer with weight paint colors is temporarily added */
931         if ((G.f & G_WEIGHTPAINT) &&
932                 (ob && ob==(G.scene->basact?G.scene->basact->object:NULL)))
933                 CustomData_duplicate_referenced_layer(&dm->faceData, CD_MCOL);
934
935         return dm;
936 }
937
938 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
939 {
940         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
941                                    BLI_countlist(&em->edges),
942                                    BLI_countlist(&em->faces));
943         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
944         EditVert *eve;
945         EditEdge *eed;
946         EditFace *efa;
947         MVert *mvert = cddm->mvert;
948         MEdge *medge = cddm->medge;
949         MFace *mface = cddm->mface;
950         int i, *index;
951
952         dm->deformedOnly = 1;
953
954         CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
955                          CD_CALLOC, dm->numVertData);
956         /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
957                          CD_CALLOC, dm->numEdgeData); */
958         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
959                          CD_CALLOC, dm->numFaceData);
960
961         /* set eve->hash to vert index */
962         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
963                 eve->tmp.l = i;
964
965         /* Need to be able to mark loose edges */
966         for(eed = em->edges.first; eed; eed = eed->next) {
967                 eed->f2 = 0;
968         }
969         for(efa = em->faces.first; efa; efa = efa->next) {
970                 efa->e1->f2 = 1;
971                 efa->e2->f2 = 1;
972                 efa->e3->f2 = 1;
973                 if(efa->e4) efa->e4->f2 = 1;
974         }
975
976         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
977         for(i = 0, eve = em->verts.first; i < dm->numVertData;
978             i++, eve = eve->next, index++) {
979                 MVert *mv = &mvert[i];
980
981                 VECCOPY(mv->co, eve->co);
982
983                 mv->no[0] = eve->no[0] * 32767.0;
984                 mv->no[1] = eve->no[1] * 32767.0;
985                 mv->no[2] = eve->no[2] * 32767.0;
986                 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
987
988                 mv->mat_nr = 0;
989                 mv->flag = 0;
990
991                 *index = i;
992
993                 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
994         }
995
996         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
997         for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
998             i++, eed = eed->next, index++) {
999                 MEdge *med = &medge[i];
1000
1001                 med->v1 = eed->v1->tmp.l;
1002                 med->v2 = eed->v2->tmp.l;
1003                 med->crease = (unsigned char) (eed->crease * 255.0f);
1004                 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1005                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1006                 
1007                 if(eed->seam) med->flag |= ME_SEAM;
1008                 if(eed->sharp) med->flag |= ME_SHARP;
1009                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1010
1011                 *index = i;
1012
1013                 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1014         }
1015
1016         index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
1017         for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1018             i++, efa = efa->next, index++) {
1019                 MFace *mf = &mface[i];
1020
1021                 mf->v1 = efa->v1->tmp.l;
1022                 mf->v2 = efa->v2->tmp.l;
1023                 mf->v3 = efa->v3->tmp.l;
1024                 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1025                 mf->mat_nr = efa->mat_nr;
1026                 mf->flag = efa->flag;
1027
1028                 *index = i;
1029
1030                 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1031                 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1032         }
1033
1034         return dm;
1035 }
1036
1037 DerivedMesh *CDDM_copy(DerivedMesh *source)
1038 {
1039         CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
1040         DerivedMesh *dm = &cddm->dm;
1041         int numVerts = source->numVertData;
1042         int numEdges = source->numEdgeData;
1043         int numFaces = source->numFaceData;
1044
1045         /* this initializes dm, and copies all non mvert/medge/mface layers */
1046         DM_from_template(dm, source, numVerts, numEdges, numFaces);
1047         dm->deformedOnly = source->deformedOnly;
1048
1049         CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
1050         CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
1051         CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
1052
1053         /* now add mvert/medge/mface layers */
1054         cddm->mvert = source->dupVertArray(source);
1055         cddm->medge = source->dupEdgeArray(source);
1056         cddm->mface = source->dupFaceArray(source);
1057
1058         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
1059         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
1060         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
1061
1062         return dm;
1063 }
1064
1065 DerivedMesh *CDDM_from_template(DerivedMesh *source,
1066                                 int numVerts, int numEdges, int numFaces)
1067 {
1068         CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
1069         DerivedMesh *dm = &cddm->dm;
1070
1071         /* this does a copy of all non mvert/medge/mface layers */
1072         DM_from_template(dm, source, numVerts, numEdges, numFaces);
1073
1074         /* now add mvert/medge/mface layers */
1075         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1076         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1077         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1078
1079         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1080         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1081         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1082
1083         return dm;
1084 }
1085
1086 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
1087 {
1088         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1089         MVert *vert;
1090         int i;
1091
1092         /* this will just return the pointer if it wasn't a referenced layer */
1093         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1094         cddm->mvert = vert;
1095
1096         for(i = 0; i < dm->numVertData; ++i, ++vert)
1097                 VECCOPY(vert->co, vertCoords[i]);
1098 }
1099
1100 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
1101 {
1102         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1103         MVert *vert;
1104         int i;
1105
1106         /* this will just return the pointer if it wasn't a referenced layer */
1107         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1108         cddm->mvert = vert;
1109
1110         for(i = 0; i < dm->numVertData; ++i, ++vert)
1111                 VECCOPY(vert->no, vertNormals[i]);
1112 }
1113
1114 /* adapted from mesh_calc_normals */
1115 void CDDM_calc_normals(DerivedMesh *dm)
1116 {
1117         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1118         float (*temp_nors)[3];
1119         float (*face_nors)[3];
1120         int i;
1121         int numVerts = dm->numVertData;
1122         int numFaces = dm->numFaceData;
1123         MFace *mf;
1124         MVert *mv;
1125
1126         if(numVerts == 0) return;
1127
1128         temp_nors = MEM_callocN(numVerts * sizeof(*temp_nors),
1129                                 "CDDM_calc_normals temp_nors");
1130
1131         /* we don't want to overwrite any referenced layers */
1132         mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1133         cddm->mvert = mv;
1134
1135         /* make a face normal layer if not present */
1136         face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
1137         if(!face_nors)
1138                 face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
1139                                                  NULL, dm->numFaceData);
1140
1141         /* calculate face normals and add to vertex normals */
1142         mf = CDDM_get_faces(dm);
1143         for(i = 0; i < numFaces; i++, mf++) {
1144                 float *f_no = face_nors[i];
1145
1146                 if(mf->v4)
1147                         CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
1148                                        mv[mf->v3].co, mv[mf->v4].co, f_no);
1149                 else
1150                         CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
1151                                       mv[mf->v3].co, f_no);
1152                 
1153                 VecAddf(temp_nors[mf->v1], temp_nors[mf->v1], f_no);
1154                 VecAddf(temp_nors[mf->v2], temp_nors[mf->v2], f_no);
1155                 VecAddf(temp_nors[mf->v3], temp_nors[mf->v3], f_no);
1156                 if(mf->v4)
1157                         VecAddf(temp_nors[mf->v4], temp_nors[mf->v4], f_no);
1158         }
1159
1160         /* normalize vertex normals and assign */
1161         for(i = 0; i < numVerts; i++, mv++) {
1162                 float *no = temp_nors[i];
1163                 
1164                 if (Normalize(no) == 0.0) {
1165                         VECCOPY(no, mv->co);
1166                         Normalize(no);
1167                 }
1168
1169                 mv->no[0] = (short)(no[0] * 32767.0);
1170                 mv->no[1] = (short)(no[1] * 32767.0);
1171                 mv->no[2] = (short)(no[2] * 32767.0);
1172         }
1173         
1174         MEM_freeN(temp_nors);
1175 }
1176
1177 void CDDM_calc_edges(DerivedMesh *dm)
1178 {
1179         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1180         CustomData edgeData;
1181         EdgeHashIterator *ehi;
1182         MFace *mf = cddm->mface;
1183         MEdge *med;
1184         EdgeHash *eh = BLI_edgehash_new();
1185         int i, *index, numEdges, maxFaces = dm->numFaceData;
1186
1187         for (i = 0; i < maxFaces; i++, mf++) {
1188                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
1189                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
1190                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
1191                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
1192                 
1193                 if (mf->v4) {
1194                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
1195                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
1196                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
1197                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
1198                 } else {
1199                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
1200                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
1201                 }
1202         }
1203
1204         numEdges = BLI_edgehash_size(eh);
1205
1206         /* write new edges into a temporary CustomData */
1207         memset(&edgeData, 0, sizeof(edgeData));
1208         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1209         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1210
1211         ehi = BLI_edgehashIterator_new(eh);
1212         med = CustomData_get_layer(&edgeData, CD_MEDGE);
1213         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
1214         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
1215             BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
1216                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
1217
1218                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1219                 *index = ORIGINDEX_NONE;
1220         }
1221         BLI_edgehashIterator_free(ehi);
1222
1223         /* free old CustomData and assign new one */
1224         CustomData_free(&dm->edgeData, dm->numVertData);
1225         dm->edgeData = edgeData;
1226         dm->numEdgeData = numEdges;
1227
1228         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1229
1230         BLI_edgehash_free(eh, NULL);
1231 }
1232
1233 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
1234 {
1235         if (numVerts < dm->numVertData)
1236                 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
1237
1238         dm->numVertData = numVerts;
1239 }
1240
1241 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
1242 {
1243         if (numEdges < dm->numEdgeData)
1244                 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
1245
1246         dm->numEdgeData = numEdges;
1247 }
1248
1249 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
1250 {
1251         if (numFaces < dm->numFaceData)
1252                 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
1253
1254         dm->numFaceData = numFaces;
1255 }
1256
1257 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
1258 {
1259         return &((CDDerivedMesh*)dm)->mvert[index];
1260 }
1261
1262 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
1263 {
1264         return &((CDDerivedMesh*)dm)->medge[index];
1265 }
1266
1267 MFace *CDDM_get_face(DerivedMesh *dm, int index)
1268 {
1269         return &((CDDerivedMesh*)dm)->mface[index];
1270 }
1271
1272 MVert *CDDM_get_verts(DerivedMesh *dm)
1273 {
1274         return ((CDDerivedMesh*)dm)->mvert;
1275 }
1276
1277 MEdge *CDDM_get_edges(DerivedMesh *dm)
1278 {
1279         return ((CDDerivedMesh*)dm)->medge;
1280 }
1281
1282 MFace *CDDM_get_faces(DerivedMesh *dm)
1283 {
1284         return ((CDDerivedMesh*)dm)->mface;
1285 }
1286