Integration of the Google Summer of Code Modifier Stack Upgrade project. The
[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_DerivedMesh.h"
41 #include "BKE_displist.h"
42 #include "BKE_mesh.h"
43 #include "BKE_utildefines.h"
44
45 #include "BLI_arithb.h"
46 #include "BLI_blenlib.h"
47 #include "BLI_edgehash.h"
48 #include "BLI_editVert.h"
49 #include "BLI_ghash.h"
50
51 #include "DNA_mesh_types.h"
52 #include "DNA_meshdata_types.h"
53
54 #include "MEM_guardedalloc.h"
55
56 #include <string.h>
57 #include <limits.h>
58
59
60 /**************** DerivedMesh interface functions ****************/
61 static int cdDM_getNumVerts(DerivedMesh *dm)
62 {
63         return dm->vertData.numElems;
64 }
65
66 static int cdDM_getNumFaces(DerivedMesh *dm)
67 {
68         return dm->faceData.numElems;
69 }
70
71 static int cdDM_getNumEdges(DerivedMesh *dm)
72 {
73         return dm->edgeData.numElems;
74 }
75
76 static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
77 {
78         *vert_r = *CDDM_get_vert(dm, index);
79 }
80
81 static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
82 {
83         *edge_r = *CDDM_get_edge(dm, index);
84 }
85
86 static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
87 {
88         *face_r = *CDDM_get_face(dm, index);
89 }
90
91 static void cdDM_getVertArray(DerivedMesh *dm, MVert *vert_r)
92 {
93         memcpy(vert_r, CDDM_get_verts(dm), sizeof(*vert_r) * dm->getNumVerts(dm));
94 }
95
96 static void cdDM_getEdgeArray(DerivedMesh *dm, MEdge *edge_r)
97 {
98         memcpy(edge_r, CDDM_get_edges(dm), sizeof(*edge_r) * dm->getNumEdges(dm));
99 }
100
101 static void cdDM_getFaceArray(DerivedMesh *dm, MFace *face_r)
102 {
103         memcpy(face_r, CDDM_get_faces(dm), sizeof(*face_r) * dm->getNumFaces(dm));
104 }
105
106 static void cdDM_foreachMappedVert(
107                            DerivedMesh *dm,
108                            void (*func)(void *userData, int index, float *co,
109                                         float *no_f, short *no_s),
110                            void *userData)
111 {
112         int i;
113         int maxVerts = dm->getNumVerts(dm);
114         MVert *mv = CDDM_get_verts(dm);
115         int *index = DM_get_vert_data_layer(dm, LAYERTYPE_ORIGINDEX);
116
117         for(i = 0; i < maxVerts; i++, mv++, index++) {
118                 if(*index == ORIGINDEX_NONE) continue;
119
120                 func(userData, *index, mv->co, NULL, mv->no);
121         }
122 }
123
124 static void cdDM_foreachMappedEdge(
125                            DerivedMesh *dm,
126                            void (*func)(void *userData, int index,
127                                         float *v0co, float *v1co),
128                            void *userData)
129 {
130         int i;
131         int maxEdges = dm->getNumEdges(dm);
132         MEdge *med = CDDM_get_edges(dm);
133         MVert *mv = CDDM_get_verts(dm);
134         int *index = DM_get_edge_data_layer(dm, LAYERTYPE_ORIGINDEX);
135
136         for(i = 0; i < maxEdges; i++, med++, index++) {
137                 if(*index == ORIGINDEX_NONE) continue;
138
139                 func(userData, *index, mv[med->v1].co, mv[med->v2].co);
140         }
141 }
142
143 static void cdDM_foreachMappedFaceCenter(
144                            DerivedMesh *dm,
145                            void (*func)(void *userData, int index,
146                                         float *cent, float *no),
147                            void *userData)
148 {
149         int i;
150         int maxFaces = dm->getNumFaces(dm);
151         MFace *mf = CDDM_get_faces(dm);
152         MVert *mv = CDDM_get_verts(dm);
153         int *index = DM_get_face_data_layer(dm, LAYERTYPE_ORIGINDEX);
154
155         for(i = 0; i < maxFaces; i++, mf++, index++) {
156                 float cent[3];
157                 float no[3];
158
159                 if(*index == ORIGINDEX_NONE) continue;
160
161                 VECCOPY(cent, mv[mf->v1].co);
162                 VecAddf(cent, cent, mv[mf->v2].co);
163                 VecAddf(cent, cent, mv[mf->v3].co);
164
165                 if (mf->v4) {
166                         CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
167                                        mv[mf->v3].co, mv[mf->v4].co, no);
168                         VecAddf(cent, cent, mv[mf->v4].co);
169                         VecMulf(cent, 0.25f);
170                 } else {
171                         CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
172                                       mv[mf->v3].co, no);
173                         VecMulf(cent, 0.33333333333f);
174                 }
175
176                 func(userData, *index, cent, no);
177         }
178 }
179
180 static DispListMesh *cdDM_convertToDispListMesh(DerivedMesh *dm,
181                                                 int allowShared)
182 {
183         DispListMesh *dlm = MEM_callocN(sizeof(*dlm),
184                                         "cdDM_convertToDispListMesh dlm");
185
186         dlm->totvert = dm->vertData.numElems;
187         dlm->totedge = dm->edgeData.numElems;
188         dlm->totface = dm->faceData.numElems;
189         dlm->mvert = dm->dupVertArray(dm);
190         dlm->medge = dm->dupEdgeArray(dm);
191         dlm->mface = dm->dupFaceArray(dm);
192
193         dlm->tface = dm->getFaceDataArray(dm, LAYERTYPE_TFACE);
194         if(dlm->tface)
195                 dlm->tface = MEM_dupallocN(dlm->tface);
196
197         dlm->mcol = dm->getFaceDataArray(dm, LAYERTYPE_MCOL);
198         if(dlm->mcol)
199                 dlm->mcol = MEM_dupallocN(dlm->mcol);
200
201         dlm->nors = NULL;
202         dlm->dontFreeVerts = dlm->dontFreeOther = dlm->dontFreeNors = 0;
203
204         return dlm;
205 }
206
207 static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
208 {
209         int i;
210
211         for(i = 0; i < dm->vertData.numElems; i++) {
212                 DO_MINMAX(CDDM_get_vert(dm, i)->co, min_r, max_r);
213         }
214 }
215
216 static void cdDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
217 {
218         VECCOPY(co_r, CDDM_get_vert(dm, index)->co);
219 }
220
221 static void cdDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
222 {
223         int i;
224         MVert *mv = CDDM_get_verts(dm);
225
226         for(i = 0; i < dm->vertData.numElems; i++, mv++)
227                 VECCOPY(cos_r[i], mv->co);
228 }
229
230 static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
231 {
232         short *no = CDDM_get_vert(dm, index)->no;
233
234         no_r[0] = no[0] / 32767.f;
235         no_r[1] = no[1] / 32767.f;
236         no_r[2] = no[2] / 32767.f;
237 }
238
239 static void cdDM_drawVerts(DerivedMesh *dm)
240 {
241         int i;
242         MVert *mv = CDDM_get_verts(dm);
243
244         glBegin(GL_POINTS);
245         for(i = 0; i < dm->vertData.numElems; i++, mv++)
246                 glVertex3fv(mv->co);
247         glEnd();
248 }
249
250 static void cdDM_drawUVEdges(DerivedMesh *dm)
251 {
252         int i;
253         TFace *tf = DM_get_face_data_layer(dm, LAYERTYPE_TFACE);
254         MFace *mf = CDDM_get_faces(dm);
255
256         if(tf) {
257                 glBegin(GL_LINES);
258                 for(i = 0; i < dm->faceData.numElems; i++, tf++, mf++) {
259                         if(!(tf->flag&TF_HIDE)) {
260                                 glVertex2fv(tf->uv[0]);
261                                 glVertex2fv(tf->uv[1]);
262
263                                 glVertex2fv(tf->uv[1]);
264                                 glVertex2fv(tf->uv[2]);
265
266                                 if(!mf->v4) {
267                                         glVertex2fv(tf->uv[2]);
268                                         glVertex2fv(tf->uv[0]);
269                                 } else {
270                                         glVertex2fv(tf->uv[2]);
271                                         glVertex2fv(tf->uv[3]);
272
273                                         glVertex2fv(tf->uv[3]);
274                                         glVertex2fv(tf->uv[0]);
275                                 }
276                         }
277                 }
278                 glEnd();
279         }
280 }
281
282 static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
283 {
284         int i;
285         MEdge *medge = CDDM_get_edges(dm);
286         MVert *mvert = CDDM_get_verts(dm);
287                 
288         glBegin(GL_LINES);
289         for(i = 0; i < dm->edgeData.numElems; i++, medge++) {
290                 if((medge->flag&ME_EDGEDRAW)
291                    && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
292                         glVertex3fv(mvert[medge->v1].co);
293                         glVertex3fv(mvert[medge->v2].co);
294                 }
295         }
296         glEnd();
297 }
298
299 static void cdDM_drawLooseEdges(DerivedMesh *dm)
300 {
301         MEdge *medge = CDDM_get_edges(dm);
302         MVert *mvert = CDDM_get_verts(dm);
303         int i;
304
305         glBegin(GL_LINES);
306         for(i = 0; i < dm->edgeData.numElems; i++, medge++) {
307                 if(medge->flag&ME_LOOSEEDGE) {
308                         glVertex3fv(mvert[medge->v1].co);
309                         glVertex3fv(mvert[medge->v2].co);
310                 }
311         }
312         glEnd();
313 }
314
315 static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
316 {
317         int a;
318         int glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
319         MFace *mface = CDDM_get_faces(dm);
320         MVert *mvert = CDDM_get_verts(dm);
321
322 #define PASSVERT(index) {                                               \
323         if(shademodel == GL_SMOOTH) {                           \
324                 short *no = mvert[index].no;                    \
325                 glNormal3sv(no);                                                \
326         }                                                                                       \
327         glVertex3fv(mvert[index].co);   \
328 }
329
330         glBegin(glmode = GL_QUADS);
331         for(a = 0; a < dm->faceData.numElems; a++, mface++) {
332                 int new_glmode, new_matnr, new_shademodel;
333
334                 new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
335                 new_matnr = mface->mat_nr + 1;
336                 new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
337                 
338                 if(new_glmode != glmode || new_matnr != matnr
339                    || new_shademodel != shademodel) {
340                         glEnd();
341
342                         drawCurrentMat = setMaterial(matnr = new_matnr);
343
344                         glShadeModel(shademodel = new_shademodel);
345                         glBegin(glmode = new_glmode);
346                 } 
347                 
348                 if(drawCurrentMat) {
349                         /* TODO make this better (cache facenormals as layer?) */
350                         if(shademodel == GL_FLAT) {
351                                 float nor[3];
352                                 if(mface->v4) {
353                                         CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co,
354                                                        mvert[mface->v3].co, mvert[mface->v4].co,
355                                                        nor);
356                                 } else {
357                                         CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co,
358                                                       mvert[mface->v3].co, nor);
359                                 }
360                                 glNormal3fv(nor);
361                         }
362
363                         PASSVERT(mface->v1);
364                         PASSVERT(mface->v2);
365                         PASSVERT(mface->v3);
366                         if(mface->v4) {
367                                 PASSVERT(mface->v4);
368                         }
369                 }
370         }
371         glEnd();
372
373         glShadeModel(GL_FLAT);
374 #undef PASSVERT
375 }
376
377 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
378 {
379         int a, glmode;
380         unsigned char *cp1, *cp2;
381         MFace *mface = CDDM_get_faces(dm);
382         MVert *mvert = CDDM_get_verts(dm);
383
384         cp1 = col1;
385         if(col2) {
386                 cp2 = col2;
387         } else {
388                 cp2 = NULL;
389                 useTwoSided = 0;
390         }
391
392         /* there's a conflict here... twosided colors versus culling...? */
393         /* defined by history, only texture faces have culling option */
394         /* we need that as mesh option builtin, next to double sided lighting */
395         if(col1 && col2)
396                 glEnable(GL_CULL_FACE);
397         
398         glShadeModel(GL_SMOOTH);
399         glBegin(glmode = GL_QUADS);
400         for(a = 0; a < dm->faceData.numElems; a++, mface++, cp1 += 16) {
401                 int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
402
403                 if(new_glmode != glmode) {
404                         glEnd();
405                         glBegin(glmode = new_glmode);
406                 }
407                         
408                 glColor3ub(cp1[3], cp1[2], cp1[1]);
409                 glVertex3fv(mvert[mface->v1].co);
410                 glColor3ub(cp1[7], cp1[6], cp1[5]);
411                 glVertex3fv(mvert[mface->v2].co);
412                 glColor3ub(cp1[11], cp1[10], cp1[9]);
413                 glVertex3fv(mvert[mface->v3].co);
414                 if(mface->v4) {
415                         glColor3ub(cp1[15], cp1[14], cp1[13]);
416                         glVertex3fv(mvert[mface->v4].co);
417                 }
418                         
419                 if(useTwoSided) {
420                         glColor3ub(cp2[11], cp2[10], cp2[9]);
421                         glVertex3fv(mvert[mface->v3].co );
422                         glColor3ub(cp2[7], cp2[6], cp2[5]);
423                         glVertex3fv(mvert[mface->v2].co );
424                         glColor3ub(cp2[3], cp2[2], cp2[1]);
425                         glVertex3fv(mvert[mface->v1].co );
426                         if(mface->v4) {
427                                 glColor3ub(cp2[15], cp2[14], cp2[13]);
428                                 glVertex3fv(mvert[mface->v4].co );
429                         }
430                 }
431                 if(col2) cp2 += 16;
432         }
433         glEnd();
434
435         glShadeModel(GL_FLAT);
436         glDisable(GL_CULL_FACE);
437 }
438
439 static void cdDM_drawFacesTex_common(DerivedMesh *dm,
440                int (*drawParams)(TFace *tface, int matnr),
441                int (*drawParamsMapped)(void *userData, int index),
442                void *userData) 
443 {
444         int i;
445         MFace *mf = CDDM_get_faces(dm);
446         TFace *tf = DM_get_face_data_layer(dm, LAYERTYPE_TFACE);
447         MVert *mv = CDDM_get_verts(dm);
448         int *index = DM_get_face_data_layer(dm, LAYERTYPE_ORIGINDEX);
449
450         for(i = 0; i < dm->faceData.numElems; i++, mf++, index++) {
451                 MVert *mvert;
452                 int flag;
453                 unsigned char *cp = NULL;
454
455                 if(drawParams)
456                         if(tf) flag = drawParams(&tf[i], mf->mat_nr);
457                         else flag = drawParams(NULL, mf->mat_nr);
458                 else if(*index != ORIGINDEX_NONE)
459                         flag = drawParamsMapped(userData, *index);
460                 else
461                         flag = 0;
462
463                 if(flag == 0) {
464                         continue;
465                 } else if(flag == 1) {
466                         if(tf) {
467                                 cp = (unsigned char *)tf[i].col;
468                         } else {
469                                 cp = DM_get_face_data(dm, i, LAYERTYPE_MCOL);
470                         }
471                 }
472
473                 /* TODO make this better (cache facenormals as layer?) */
474                 if(!(mf->flag&ME_SMOOTH)) {
475                         float nor[3];
476                         if(mf->v4) {
477                                 CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
478                                                            mv[mf->v3].co, mv[mf->v4].co, nor);
479                         } else {
480                                 CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
481                                                           mv[mf->v3].co, nor);
482                         }
483                         glNormal3fv(nor);
484                 }
485
486                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
487                 if(tf) glTexCoord2fv(tf[i].uv[0]);
488                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
489                 mvert = &mv[mf->v1];
490                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
491                 glVertex3fv(mvert->co);
492                         
493                 if(tf) glTexCoord2fv(tf[i].uv[1]);
494                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
495                 mvert = &mv[mf->v2];
496                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
497                 glVertex3fv(mvert->co);
498
499                 if(tf) glTexCoord2fv(tf[i].uv[2]);
500                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
501                 mvert = &mv[mf->v3];
502                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
503                 glVertex3fv(mvert->co);
504
505                 if(mf->v4) {
506                         if(tf) glTexCoord2fv(tf[i].uv[3]);
507                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
508                         mvert = &mv[mf->v4];
509                         if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
510                         glVertex3fv(mvert->co);
511                 }
512                 glEnd();
513         }
514 }
515
516 static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(TFace *tface, int matnr))
517 {
518         cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
519 }
520
521 static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
522 {
523         int i;
524         MFace *mf = CDDM_get_faces(dm);
525         MVert *mv = CDDM_get_verts(dm);
526         int *index = DM_get_face_data_layer(dm, LAYERTYPE_ORIGINDEX);
527         TFace *tf = DM_get_face_data_layer(dm, LAYERTYPE_TFACE);
528         MCol *mc = DM_get_face_data_layer(dm, LAYERTYPE_MCOL);
529
530         for(i = 0; i < dm->faceData.numElems; i++, mf++, index++) {
531                 int drawSmooth = (mf->flag & ME_SMOOTH);
532
533                 if(setDrawOptions && *index == ORIGINDEX_NONE) continue;
534
535                 if(!setDrawOptions || setDrawOptions(userData, *index, &drawSmooth)) {
536                         unsigned char *cp = NULL;
537
538                         if(useColors) {
539                                 if(tf) {
540                                         cp = (unsigned char *)tf[i].col;
541                                 } else if(mc) {
542                                         cp = (unsigned char *)&mc[i * 4];
543                                 }
544                         }
545
546                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
547                         glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
548
549                         if(!drawSmooth) {
550                                 /* TODO make this better (cache facenormals as layer?) */
551                                 float nor[3];
552                                 if(mf->v4) {
553                                         CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
554                                                                    mv[mf->v3].co, mv[mf->v4].co, nor);
555                                 } else {
556                                         CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
557                                                                   mv[mf->v3].co, nor);
558                                 }
559                                 glNormal3fv(nor);
560
561                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
562                                 glVertex3fv(mv[mf->v1].co);
563                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
564                                 glVertex3fv(mv[mf->v2].co);
565                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
566                                 glVertex3fv(mv[mf->v3].co);
567                                 if(mf->v4) {
568                                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
569                                         glVertex3fv(mv[mf->v4].co);
570                                 }
571                         } else {
572                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
573                                 glNormal3sv(mv[mf->v1].no);
574                                 glVertex3fv(mv[mf->v1].co);
575                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
576                                 glNormal3sv(mv[mf->v2].no);
577                                 glVertex3fv(mv[mf->v2].co);
578                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
579                                 glNormal3sv(mv[mf->v3].no);
580                                 glVertex3fv(mv[mf->v3].co);
581                                 if(mf->v4) {
582                                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
583                                         glNormal3sv(mv[mf->v4].no);
584                                         glVertex3fv(mv[mf->v4].co);
585                                 }
586                         }
587
588                         glEnd();
589                 }
590         }
591 }
592
593 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
594 {
595         cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
596 }
597
598 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
599 {
600         int i;
601         int *index = DM_get_edge_data_layer(dm, LAYERTYPE_ORIGINDEX);
602         MEdge *edge = CDDM_get_edges(dm);
603         MVert *vert = CDDM_get_verts(dm);
604
605         glBegin(GL_LINES);
606         for(i = 0; i < dm->edgeData.numElems; i++, edge++, index++) {
607
608                 if(setDrawOptions && *index == ORIGINDEX_NONE) continue;
609
610                 if(!setDrawOptions || setDrawOptions(userData, *index)) {
611                         glVertex3fv(vert[edge->v1].co);
612                         glVertex3fv(vert[edge->v2].co);
613                 }
614         }
615         glEnd();
616 }
617
618 static void cdDM_release(DerivedMesh *dm)
619 {
620         CustomData_free(&dm->vertData);
621         CustomData_free(&dm->edgeData);
622         CustomData_free(&dm->faceData);
623
624         MEM_freeN(dm);
625 }
626
627
628 /**************** CDDM interface functions ****************/
629 static DerivedMesh *cdDM_create(const char *desc)
630 {
631         DerivedMesh *dm;
632
633         dm = MEM_callocN(sizeof(*dm), desc);
634
635         dm->getMinMax = cdDM_getMinMax;
636
637         dm->convertToDispListMesh = cdDM_convertToDispListMesh;
638
639         dm->getNumVerts = cdDM_getNumVerts;
640         dm->getNumFaces = cdDM_getNumFaces;
641         dm->getNumEdges = cdDM_getNumEdges;
642
643         dm->getVert = cdDM_getVert;
644         dm->getEdge = cdDM_getEdge;
645         dm->getFace = cdDM_getFace;
646         dm->getVertArray = cdDM_getVertArray;
647         dm->getEdgeArray = cdDM_getEdgeArray;
648         dm->getFaceArray = cdDM_getFaceArray;
649         dm->getVertData = DM_get_vert_data;
650         dm->getEdgeData = DM_get_edge_data;
651         dm->getFaceData = DM_get_face_data;
652         dm->getVertDataArray = DM_get_vert_data_layer;
653         dm->getEdgeDataArray = DM_get_edge_data_layer;
654         dm->getFaceDataArray = DM_get_face_data_layer;
655
656         dm->getVertCos = cdDM_getVertCos;
657         dm->getVertCo = cdDM_getVertCo;
658         dm->getVertNo = cdDM_getVertNo;
659
660         dm->drawVerts = cdDM_drawVerts;
661
662         dm->drawUVEdges = cdDM_drawUVEdges;
663         dm->drawEdges = cdDM_drawEdges;
664         dm->drawLooseEdges = cdDM_drawLooseEdges;
665         dm->drawMappedEdges = cdDM_drawMappedEdges;
666
667         dm->drawFacesSolid = cdDM_drawFacesSolid;
668         dm->drawFacesColored = cdDM_drawFacesColored;
669         dm->drawFacesTex = cdDM_drawFacesTex;
670         dm->drawMappedFaces = cdDM_drawMappedFaces;
671         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
672
673         dm->foreachMappedVert = cdDM_foreachMappedVert;
674         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
675         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
676
677         dm->release = cdDM_release;
678
679         return dm;
680 }
681
682 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
683 {
684         DerivedMesh *dm = cdDM_create("CDDM_new dm");
685         DM_init(dm, numVerts, numEdges, numFaces);
686
687         CustomData_add_layer(&dm->vertData, LAYERTYPE_MVERT, LAYERFLAG_NOCOPY,
688                              NULL);
689         CustomData_add_layer(&dm->edgeData, LAYERTYPE_MEDGE, LAYERFLAG_NOCOPY,
690                              NULL);
691         CustomData_add_layer(&dm->faceData, LAYERTYPE_MFACE, LAYERFLAG_NOCOPY,
692                              NULL);
693
694         return dm;
695 }
696
697 DerivedMesh *CDDM_from_mesh(Mesh *mesh)
698 {
699         DerivedMesh *dm = CDDM_new(mesh->totvert, mesh->totedge, mesh->totface);
700         int i;
701
702         if(mesh->msticky)
703                 CustomData_add_layer(&dm->vertData, LAYERTYPE_MSTICKY, 0, NULL);
704         if(mesh->dvert)
705                 CustomData_add_layer(&dm->vertData, LAYERTYPE_MDEFORMVERT, 0, NULL);
706
707         if(mesh->tface)
708                 CustomData_add_layer(&dm->faceData, LAYERTYPE_TFACE, 0, NULL);
709         if(mesh->mcol)
710                 CustomData_add_layer(&dm->faceData, LAYERTYPE_MCOL, 0, NULL);
711
712         for(i = 0; i < mesh->totvert; ++i) {
713                 DM_set_vert_data(dm, i, LAYERTYPE_MVERT, &mesh->mvert[i]);
714                 if(mesh->msticky)
715                         DM_set_vert_data(dm, i, LAYERTYPE_MSTICKY, &mesh->msticky[i]);
716                 if(mesh->dvert)
717                         DM_set_vert_data(dm, i, LAYERTYPE_MDEFORMVERT, &mesh->dvert[i]);
718
719                 DM_set_vert_data(dm, i, LAYERTYPE_ORIGINDEX, &i);
720         }
721
722         for(i = 0; i < mesh->totedge; ++i) {
723                 DM_set_edge_data(dm, i, LAYERTYPE_MEDGE, &mesh->medge[i]);
724
725                 DM_set_edge_data(dm, i, LAYERTYPE_ORIGINDEX, &i);
726         }
727
728         for(i = 0; i < mesh->totface; ++i) {
729                 DM_set_face_data(dm, i, LAYERTYPE_MFACE, &mesh->mface[i]);
730                 if(mesh->tface)
731                         DM_set_face_data(dm, i, LAYERTYPE_TFACE, &mesh->tface[i]);
732                 if(mesh->mcol)
733                         DM_set_face_data(dm, i, LAYERTYPE_MCOL, &mesh->mcol[i * 4]);
734
735                 DM_set_face_data(dm, i, LAYERTYPE_ORIGINDEX, &i);
736         }
737
738         return dm;
739 }
740
741 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
742 {
743         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
744                                    BLI_countlist(&em->edges),
745                                    BLI_countlist(&em->faces));
746         EditVert *eve;
747         EditEdge *eed;
748         EditFace *efa;
749         int i;
750         MVert *mvert = CDDM_get_verts(dm);
751         MEdge *medge = CDDM_get_edges(dm);
752         MFace *mface = CDDM_get_faces(dm);
753         int *index;
754
755         /* this maps from vert pointer to vert index */
756         GHash *vertHash = BLI_ghash_new(BLI_ghashutil_ptrhash,
757                                         BLI_ghashutil_ptrcmp);
758
759         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
760                 BLI_ghash_insert(vertHash, eve, (void *)i);
761
762         if(me->msticky)
763                 CustomData_add_layer(&dm->vertData, LAYERTYPE_MDEFORMVERT, 0, NULL);
764         if(me->dvert)
765                 CustomData_add_layer(&dm->vertData, LAYERTYPE_MDEFORMVERT, 0, NULL);
766
767         if(me->tface)
768                 CustomData_add_layer(&dm->faceData, LAYERTYPE_TFACE, 0, NULL);
769
770         /* Need to be able to mark loose edges */
771         for(eed = em->edges.first; eed; eed = eed->next) {
772                 eed->f2 = 0;
773         }
774         for(efa = em->faces.first; efa; efa = efa->next) {
775                 efa->e1->f2 = 1;
776                 efa->e2->f2 = 1;
777                 efa->e3->f2 = 1;
778                 if(efa->e4) efa->e4->f2 = 1;
779         }
780
781         index = dm->getVertDataArray(dm, LAYERTYPE_ORIGINDEX);
782         for(i = 0, eve = em->verts.first; i < dm->vertData.numElems;
783             i++, eve = eve->next, index++) {
784                 MVert *mv = &mvert[i];
785
786                 VECCOPY(mv->co, eve->co);
787
788                 mv->no[0] = eve->no[0] * 32767.0;
789                 mv->no[1] = eve->no[1] * 32767.0;
790                 mv->no[2] = eve->no[2] * 32767.0;
791
792                 mv->mat_nr = 0;
793                 mv->flag = 0;
794
795                 *index = i;
796
797                 if(me->msticky && eve->keyindex != -1)
798                         DM_set_vert_data(dm, i, LAYERTYPE_MSTICKY,
799                                          &me->msticky[eve->keyindex]);
800                 if(me->dvert && eve->keyindex != -1)
801                         DM_set_vert_data(dm, i, LAYERTYPE_MDEFORMVERT,
802                                          &me->dvert[eve->keyindex]);
803         }
804
805         index = dm->getEdgeDataArray(dm, LAYERTYPE_ORIGINDEX);
806         for(i = 0, eed = em->edges.first; i < dm->edgeData.numElems;
807             i++, eed = eed->next, index++) {
808                 MEdge *med = &medge[i];
809
810                 med->v1 = (int) BLI_ghash_lookup(vertHash, eed->v1);
811                 med->v2 = (int) BLI_ghash_lookup(vertHash, eed->v2);
812                 med->crease = (unsigned char) (eed->crease * 255.0f);
813                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
814                 
815                 if(eed->seam) med->flag |= ME_SEAM;
816                 if(eed->sharp) med->flag |= ME_SHARP;
817                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
818
819                 *index = i;
820         }
821
822         index = dm->getFaceDataArray(dm, LAYERTYPE_ORIGINDEX);
823         for(i = 0, efa = em->faces.first; i < dm->faceData.numElems;
824             i++, efa = efa->next, index++) {
825                 MFace *mf = &mface[i];
826
827                 mf->v1 = (int) BLI_ghash_lookup(vertHash, efa->v1);
828                 mf->v2 = (int) BLI_ghash_lookup(vertHash, efa->v2);
829                 mf->v3 = (int) BLI_ghash_lookup(vertHash, efa->v3);
830                 mf->v4 = efa->v4 ? (int)BLI_ghash_lookup(vertHash, efa->v4) : 0;
831                 mf->mat_nr = efa->mat_nr;
832                 mf->flag = efa->flag;
833                 test_index_face(mf, NULL, NULL, efa->v4?4:3);
834
835                 *index = i;
836
837                 if(me->tface)
838                         DM_set_face_data(dm, i, LAYERTYPE_TFACE, &efa->tf);
839         }
840
841         BLI_ghash_free(vertHash, NULL, NULL);
842
843         return dm;
844 }
845
846 DerivedMesh *CDDM_copy(DerivedMesh *source)
847 {
848         DerivedMesh *dest = CDDM_from_template(source,
849                                                source->vertData.numElems,
850                                                source->edgeData.numElems,
851                                                source->faceData.numElems);
852
853         CustomData_copy_data(&source->vertData, &dest->vertData, 0, 0,
854                              source->vertData.numElems);
855         CustomData_copy_data(&source->edgeData, &dest->edgeData, 0, 0,
856                              source->edgeData.numElems);
857         CustomData_copy_data(&source->faceData, &dest->faceData, 0, 0,
858                              source->faceData.numElems);
859
860         /* copy vert/face/edge data from source */
861         source->getVertArray(source, CDDM_get_verts(dest));
862         source->getEdgeArray(source, CDDM_get_edges(dest));
863         source->getFaceArray(source, CDDM_get_faces(dest));
864
865         return dest;
866 }
867
868 DerivedMesh *CDDM_from_template(DerivedMesh *source,
869                                 int numVerts, int numEdges, int numFaces)
870 {
871         DerivedMesh *dest = cdDM_create("CDDM_from_template dest");
872         DM_from_template(dest, source, numVerts, numEdges, numFaces);
873
874         /* if no vert/face/edge layers in custom data, add them */
875         if(!CDDM_get_verts(dest))
876                 CustomData_add_layer(&dest->vertData, LAYERTYPE_MVERT,
877                                      LAYERFLAG_NOCOPY, NULL);
878         if(!CDDM_get_edges(dest))
879                 CustomData_add_layer(&dest->edgeData, LAYERTYPE_MEDGE,
880                                      LAYERFLAG_NOCOPY, NULL);
881         if(!CDDM_get_faces(dest))
882                 CustomData_add_layer(&dest->faceData, LAYERTYPE_MFACE,
883                                      LAYERFLAG_NOCOPY, NULL);
884
885         return dest;
886 }
887
888 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
889 {
890         int i;
891         MVert *vert = CDDM_get_verts(dm);
892
893         for(i = 0; i < dm->vertData.numElems; ++i, ++vert)
894                 VECCOPY(vert->co, vertCoords[i]);
895 }
896
897 /* adapted from mesh_calc_normals */
898 void CDDM_calc_normals(DerivedMesh *dm)
899 {
900         float (*temp_nors)[3];
901         float (*face_nors)[3];
902         int i;
903         int numVerts = dm->getNumVerts(dm);
904         int numFaces = dm->getNumFaces(dm);
905         MFace *mf;
906         MVert *mv = CDDM_get_verts(dm);
907
908         if(!mv) return;
909
910         temp_nors = MEM_callocN(numVerts * sizeof(*temp_nors),
911                                 "CDDM_calc_normals temp_nors");
912         face_nors = MEM_mallocN(numFaces * sizeof(*face_nors),
913                                 "CDDM_calc_normals face_nors");
914
915         mf = CDDM_get_faces(dm);
916         for(i = 0; i < numFaces; i++, mf++) {
917                 float *f_no = face_nors[i];
918
919                 if(mf->v4)
920                         CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
921                                        mv[mf->v3].co, mv[mf->v4].co, f_no);
922                 else
923                         CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
924                                       mv[mf->v3].co, f_no);
925                 
926                 VecAddf(temp_nors[mf->v1], temp_nors[mf->v1], f_no);
927                 VecAddf(temp_nors[mf->v2], temp_nors[mf->v2], f_no);
928                 VecAddf(temp_nors[mf->v3], temp_nors[mf->v3], f_no);
929                 if(mf->v4)
930                         VecAddf(temp_nors[mf->v4], temp_nors[mf->v4], f_no);
931         }
932
933         for(i = 0; i < numVerts; i++, mv++) {
934                 float *no = temp_nors[i];
935                 
936                 if (Normalise(no) == 0.0) {
937                         VECCOPY(no, mv->co);
938                         Normalise(no);
939                 }
940
941                 mv->no[0] = (short)(no[0] * 32767.0);
942                 mv->no[1] = (short)(no[1] * 32767.0);
943                 mv->no[2] = (short)(no[2] * 32767.0);
944         }
945         
946         MEM_freeN(temp_nors);
947
948         /* TODO maybe cache face normals here? */
949         MEM_freeN(face_nors);
950 }
951
952 void CDDM_calc_edges(DerivedMesh *dm)
953 {
954         CustomData edgeData;
955         EdgeHash *eh = BLI_edgehash_new();
956         EdgeHashIterator *ehi;
957         int i;
958         int maxFaces = dm->getNumFaces(dm);
959         MFace *mf = CDDM_get_faces(dm);
960         MEdge *med;
961
962         for (i = 0; i < maxFaces; i++, mf++) {
963                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
964                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
965                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
966                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
967                 
968                 if (mf->v4) {
969                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
970                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
971                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
972                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
973                 } else {
974                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
975                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
976                 }
977         }
978
979         CustomData_from_template(&dm->edgeData, &edgeData, BLI_edgehash_size(eh));
980
981         if(!CustomData_get_layer(&edgeData, LAYERTYPE_MEDGE))
982                 CustomData_add_layer(&edgeData, LAYERTYPE_MEDGE,
983                                      LAYERFLAG_NOCOPY, NULL);
984
985         ehi = BLI_edgehashIterator_new(eh);
986         med = CustomData_get_layer(&edgeData, LAYERTYPE_MEDGE);
987         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
988             BLI_edgehashIterator_step(ehi), ++i, ++med) {
989                 BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2);
990
991                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
992         }
993         BLI_edgehashIterator_free(ehi);
994
995         CustomData_free(&dm->edgeData);
996         dm->edgeData = edgeData;
997
998         BLI_edgehash_free(eh, NULL);
999 }
1000
1001 void CDDM_set_num_verts(DerivedMesh *dm, int numVerts)
1002 {
1003         CustomData_set_num_elems(&dm->vertData, numVerts);
1004 }
1005
1006 void CDDM_set_num_edges(DerivedMesh *dm, int numEdges)
1007 {
1008         CustomData_set_num_elems(&dm->edgeData, numEdges);
1009 }
1010
1011 void CDDM_set_num_faces(DerivedMesh *dm, int numFaces)
1012 {
1013         CustomData_set_num_elems(&dm->faceData, numFaces);
1014 }
1015
1016 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
1017 {
1018         return CustomData_get(&dm->vertData, index, LAYERTYPE_MVERT);
1019 }
1020
1021 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
1022 {
1023         return CustomData_get(&dm->edgeData, index, LAYERTYPE_MEDGE);
1024 }
1025
1026 MFace *CDDM_get_face(DerivedMesh *dm, int index)
1027 {
1028         return CustomData_get(&dm->faceData, index, LAYERTYPE_MFACE);
1029 }
1030
1031 MVert *CDDM_get_verts(DerivedMesh *dm)
1032 {
1033         return CustomData_get_layer(&dm->vertData, LAYERTYPE_MVERT);
1034 }
1035
1036 MEdge *CDDM_get_edges(DerivedMesh *dm)
1037 {
1038         return CustomData_get_layer(&dm->edgeData, LAYERTYPE_MEDGE);
1039 }
1040
1041 MFace *CDDM_get_faces(DerivedMesh *dm)
1042 {
1043         return CustomData_get_layer(&dm->faceData, LAYERTYPE_MFACE);
1044 }
1045