4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2006 Blender Foundation.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): Ben Batt <benbatt@gmail.com>
27 * ***** END GPL LICENSE BLOCK *****
29 * Implementation of CDDerivedMesh.
31 * BKE_cdderivedmesh.h contains the function prototypes for this file.
35 /* TODO maybe BIF_gl.h should include string.h? */
39 #include "BKE_cdderivedmesh.h"
40 #include "BKE_global.h"
42 #include "BKE_utildefines.h"
45 #include "BLI_blenlib.h"
46 #include "BLI_edgehash.h"
47 #include "BLI_editVert.h"
50 #include "DNA_meshdata_types.h"
51 #include "DNA_object_types.h"
52 #include "DNA_curve_types.h" /* for Curve */
54 #include "MEM_guardedalloc.h"
56 #include "gpu_buffers.h"
58 #include "GPU_extensions.h"
59 #include "GPU_material.h"
68 /* these point to data in the DerivedMesh custom data layers,
69 they are only here for efficiency and convenience **/
76 /* Mesh connectivity */
77 struct ListBase *fmap;
78 struct IndexNode *fmap_mem;
81 /**************** DerivedMesh interface functions ****************/
82 static int cdDM_getNumVerts(DerivedMesh *dm)
84 return dm->numVertData;
87 static int cdDM_getNumEdges(DerivedMesh *dm)
89 return dm->numEdgeData;
92 static int cdDM_getNumFaces(DerivedMesh *dm)
94 return dm->numFaceData;
97 static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
99 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
100 *vert_r = cddm->mvert[index];
103 static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
105 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
106 *edge_r = cddm->medge[index];
109 static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
111 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
112 *face_r = cddm->mface[index];
115 static void cdDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
117 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
118 memcpy(vert_r, cddm->mvert, sizeof(*vert_r) * dm->numVertData);
121 static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
123 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
124 memcpy(edge_r, cddm->medge, sizeof(*edge_r) * dm->numEdgeData);
127 static void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
129 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
130 memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData);
133 static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
135 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
138 if (dm->numVertData) {
139 for (i=0; i<dm->numVertData; i++) {
140 DO_MINMAX(cddm->mvert[i].co, min_r, max_r);
143 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
147 static void cdDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
149 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
151 VECCOPY(co_r, cddm->mvert[index].co);
154 static void cdDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
156 MVert *mv = CDDM_get_verts(dm);
159 for(i = 0; i < dm->numVertData; i++, mv++)
160 VECCOPY(cos_r[i], mv->co);
163 static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
165 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
166 short *no = cddm->mvert[index].no;
168 no_r[0] = no[0]/32767.f;
169 no_r[1] = no[1]/32767.f;
170 no_r[2] = no[2]/32767.f;
173 static ListBase *cdDM_getFaceMap(Object *ob, DerivedMesh *dm)
175 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
177 if(!cddm->fmap && ob->type == OB_MESH) {
180 create_vert_face_map(&cddm->fmap, &cddm->fmap_mem, me->mface,
181 me->totvert, me->totface);
187 static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
189 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
191 if(!cddm->pbvh && ob->type == OB_MESH) {
194 cddm->pbvh = BLI_pbvh_new();
195 BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
196 me->totface, me->totvert);
202 static void cdDM_drawVerts(DerivedMesh *dm)
204 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
205 MVert *mv = cddm->mvert;
208 if( GPU_buffer_legacy(dm) ) {
210 for(i = 0; i < dm->numVertData; i++, mv++)
214 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
215 GPU_vertex_setup(dm);
216 if( !GPU_buffer_legacy(dm) ) {
217 glDrawArrays(GL_POINTS,0,dm->drawObject->nelements);
223 static void cdDM_drawUVEdges(DerivedMesh *dm)
225 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
226 MFace *mf = cddm->mface;
227 MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
231 if( GPU_buffer_legacy(dm) ) {
233 for(i = 0; i < dm->numFaceData; i++, mf++, tf++) {
234 if(!(mf->flag&ME_HIDE)) {
235 glVertex2fv(tf->uv[0]);
236 glVertex2fv(tf->uv[1]);
238 glVertex2fv(tf->uv[1]);
239 glVertex2fv(tf->uv[2]);
242 glVertex2fv(tf->uv[2]);
243 glVertex2fv(tf->uv[0]);
245 glVertex2fv(tf->uv[2]);
246 glVertex2fv(tf->uv[3]);
248 glVertex2fv(tf->uv[3]);
249 glVertex2fv(tf->uv[0]);
261 GPU_uvedge_setup(dm);
262 if( !GPU_buffer_legacy(dm) ) {
263 for(i = 0; i < dm->numFaceData; i++, mf++) {
264 if(mf->flag&ME_LOOSEEDGE) {
270 if( prevdraw != draw ) {
271 if( prevdraw > 0 && (curpos-prevstart) > 0) {
272 glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
284 if( prevdraw > 0 && (curpos-prevstart) > 0 ) {
285 glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
293 static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
295 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
296 MVert *mvert = cddm->mvert;
297 MEdge *medge = cddm->medge;
300 if( GPU_buffer_legacy(dm) ) {
301 DEBUG_VBO( "Using legacy code. cdDM_drawEdges\n" );
303 for(i = 0; i < dm->numEdgeData; i++, medge++) {
304 if((medge->flag&ME_EDGEDRAW)
305 && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
306 glVertex3fv(mvert[medge->v1].co);
307 glVertex3fv(mvert[medge->v2].co);
312 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
318 if( !GPU_buffer_legacy(dm) ) {
319 for(i = 0; i < dm->numEdgeData; i++, medge++) {
320 if((medge->flag&ME_EDGEDRAW)
321 && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
327 if( prevdraw != draw ) {
328 if( prevdraw > 0 && (i-prevstart) > 0 ) {
329 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 );
335 if( prevdraw > 0 && (i-prevstart) > 0 ) {
336 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 );
343 static void cdDM_drawLooseEdges(DerivedMesh *dm)
345 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
346 MVert *mvert = cddm->mvert;
347 MEdge *medge = cddm->medge;
350 if( GPU_buffer_legacy(dm) ) {
351 DEBUG_VBO( "Using legacy code. cdDM_drawLooseEdges\n" );
353 for(i = 0; i < dm->numEdgeData; i++, medge++) {
354 if(medge->flag&ME_LOOSEEDGE) {
355 glVertex3fv(mvert[medge->v1].co);
356 glVertex3fv(mvert[medge->v2].co);
361 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
367 if( !GPU_buffer_legacy(dm) ) {
368 for(i = 0; i < dm->numEdgeData; i++, medge++) {
369 if(medge->flag&ME_LOOSEEDGE) {
375 if( prevdraw != draw ) {
376 if( prevdraw > 0 && (i-prevstart) > 0) {
377 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 );
383 if( prevdraw > 0 && (i-prevstart) > 0 ) {
384 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 );
391 static void cdDM_drawFacesSolid(DerivedMesh *dm,
392 float (*partial_redraw_planes)[4],
393 int fast, int (*setMaterial)(int, void *attribs))
395 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
396 MVert *mvert = cddm->mvert;
397 MFace *mface = cddm->mface;
398 float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
399 int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
401 #define PASSVERT(index) { \
402 if(shademodel == GL_SMOOTH) { \
403 short *no = mvert[index].no; \
406 glVertex3fv(mvert[index].co); \
410 if(dm->numFaceData) {
411 float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
413 /* should be per face */
414 if(!setMaterial(mface->mat_nr+1, NULL))
417 glShadeModel((mface->flag & ME_SMOOTH)? GL_SMOOTH: GL_FLAT);
418 BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors);
419 glShadeModel(GL_FLAT);
425 if( GPU_buffer_legacy(dm) ) {
426 DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" );
427 glBegin(glmode = GL_QUADS);
428 for(a = 0; a < dm->numFaceData; a++, mface++) {
429 int new_glmode, new_matnr, new_shademodel;
431 new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
432 new_matnr = mface->mat_nr + 1;
433 new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
435 if(new_glmode != glmode || new_matnr != matnr
436 || new_shademodel != shademodel) {
439 drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
441 glShadeModel(shademodel = new_shademodel);
442 glBegin(glmode = new_glmode);
446 if(shademodel == GL_FLAT) {
451 /* TODO make this better (cache facenormals as layer?) */
454 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
456 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
474 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
475 GPU_vertex_setup( dm );
476 GPU_normal_setup( dm );
477 if( !GPU_buffer_legacy(dm) ) {
478 glShadeModel(GL_SMOOTH);
479 for( a = 0; a < dm->drawObject->nmaterials; a++ ) {
480 if( setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL) )
481 glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start, dm->drawObject->materials[a].end-dm->drawObject->materials[a].start);
484 GPU_buffer_unbind( );
488 glShadeModel(GL_FLAT);
491 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
493 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
495 unsigned char *cp1, *cp2;
496 MVert *mvert = cddm->mvert;
497 MFace *mface = cddm->mface;
507 /* there's a conflict here... twosided colors versus culling...? */
508 /* defined by history, only texture faces have culling option */
509 /* we need that as mesh option builtin, next to double sided lighting */
511 glEnable(GL_CULL_FACE);
513 if( GPU_buffer_legacy(dm) ) {
514 DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" );
515 glShadeModel(GL_SMOOTH);
516 glBegin(glmode = GL_QUADS);
517 for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
518 int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
520 if(new_glmode != glmode) {
522 glBegin(glmode = new_glmode);
525 glColor3ub(cp1[0], cp1[1], cp1[2]);
526 glVertex3fv(mvert[mface->v1].co);
527 glColor3ub(cp1[4], cp1[5], cp1[6]);
528 glVertex3fv(mvert[mface->v2].co);
529 glColor3ub(cp1[8], cp1[9], cp1[10]);
530 glVertex3fv(mvert[mface->v3].co);
532 glColor3ub(cp1[12], cp1[13], cp1[14]);
533 glVertex3fv(mvert[mface->v4].co);
537 glColor3ub(cp2[8], cp2[9], cp2[10]);
538 glVertex3fv(mvert[mface->v3].co );
539 glColor3ub(cp2[4], cp2[5], cp2[6]);
540 glVertex3fv(mvert[mface->v2].co );
541 glColor3ub(cp2[0], cp2[1], cp2[2]);
542 glVertex3fv(mvert[mface->v1].co );
544 glColor3ub(cp2[12], cp2[13], cp2[14]);
545 glVertex3fv(mvert[mface->v4].co );
552 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
553 GPU_color4_upload(dm,cp1);
554 GPU_vertex_setup(dm);
556 if( !GPU_buffer_legacy(dm) ) {
557 glShadeModel(GL_SMOOTH);
558 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
561 GPU_color4_upload(dm,cp2);
563 glCullFace(GL_FRONT);
564 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
571 glShadeModel(GL_FLAT);
572 glDisable(GL_CULL_FACE);
575 static void cdDM_drawFacesTex_common(DerivedMesh *dm,
576 int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
577 int (*drawParamsMapped)(void *userData, int index),
580 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
581 MVert *mv = cddm->mvert;
582 MFace *mf = DM_get_face_data_layer(dm, CD_MFACE);
583 MCol *realcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL);
584 float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
585 MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
586 int i, j, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
587 int startFace = 0, lastFlag = 0xdeadbeef;
588 MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
590 mcol = dm->getFaceDataArray(dm, CD_MCOL);
592 if( GPU_buffer_legacy(dm) ) {
593 DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
594 for(i = 0; i < dm->numFaceData; i++, mf++) {
597 unsigned char *cp = NULL;
600 flag = drawParams(tf? &tf[i]: NULL, mcol? &mcol[i*4]: NULL, mf->mat_nr);
605 if(orig == ORIGINDEX_NONE) { if(nors) nors += 3; continue; }
606 if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
607 else { if(nors) nors += 3; continue; }
610 if(drawParamsMapped) flag = drawParamsMapped(userData, i);
611 else { if(nors) nors += 3; continue; }
616 cp= (unsigned char*) &mcol[i*4];
618 if(!(mf->flag&ME_SMOOTH)) {
625 normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
627 normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
633 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
634 if(tf) glTexCoord2fv(tf[i].uv[0]);
635 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
637 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
638 glVertex3fv(mvert->co);
640 if(tf) glTexCoord2fv(tf[i].uv[1]);
641 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
643 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
644 glVertex3fv(mvert->co);
646 if(tf) glTexCoord2fv(tf[i].uv[2]);
647 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
649 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
650 glVertex3fv(mvert->co);
653 if(tf) glTexCoord2fv(tf[i].uv[3]);
654 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
656 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
657 glVertex3fv(mvert->co);
664 } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
669 GPU_vertex_setup( dm );
670 GPU_normal_setup( dm );
673 /*if( realcol && dm->drawObject->colType == CD_TEXTURE_MCOL ) {
675 } else if( mcol && dm->drawObject->colType == CD_MCOL ) {
680 unsigned char *colors = MEM_mallocN(dm->getNumFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
681 for( i=0; i < dm->getNumFaces(dm); i++ ) {
682 for( j=0; j < 4; j++ ) {
683 colors[i*12+j*3] = col[i*4+j].r;
684 colors[i*12+j*3+1] = col[i*4+j].g;
685 colors[i*12+j*3+2] = col[i*4+j].b;
688 GPU_color3_upload(dm,colors);
691 dm->drawObject->colType = CD_TEXTURE_MCOL;
693 dm->drawObject->colType = CD_MCOL;
695 GPU_color_setup( dm );
698 if( !GPU_buffer_legacy(dm) ) {
699 glShadeModel( GL_SMOOTH );
700 for(i = 0; i < dm->drawObject->nelements/3; i++) {
701 int actualFace = dm->drawObject->faceRemap[i];
705 flag = drawParams(tf? &tf[actualFace]: NULL, mcol? &mcol[actualFace*4]: NULL, mf[actualFace].mat_nr);
709 orig = index[actualFace];
711 flag = drawParamsMapped(userData, orig);
715 flag = drawParamsMapped(userData, actualFace);
717 if( flag != lastFlag ) {
718 if( startFace < i ) {
719 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
720 if (lastFlag==1 && mcol)
724 glDrawArrays(GL_TRIANGLES,startFace*3,(i-startFace)*3);
731 if( startFace < dm->drawObject->nelements/3 ) {
732 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
733 if (lastFlag==1 && mcol)
737 glDrawArrays(GL_TRIANGLES,startFace*3,dm->drawObject->nelements-startFace*3);
743 glShadeModel( GL_FLAT );
747 static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
749 cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
752 static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
754 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
755 MVert *mv = cddm->mvert;
756 MFace *mf = cddm->mface;
758 float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
759 int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
761 mc = DM_get_face_data_layer(dm, CD_ID_MCOL);
763 mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
765 mc = DM_get_face_data_layer(dm, CD_MCOL);
767 /* back-buffer always uses legacy since VBO's would need the
768 * color array temporarily overwritten for drawing, then reset. */
769 if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) {
770 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" );
771 for(i = 0; i < dm->numFaceData; i++, mf++) {
772 int drawSmooth = (mf->flag & ME_SMOOTH);
776 if(setDrawOptions && orig == ORIGINDEX_NONE)
777 { if(nors) nors += 3; continue; }
782 if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) {
783 unsigned char *cp = NULL;
786 cp = (unsigned char *)&mc[i * 4];
788 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
789 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
798 normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
800 normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
805 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
806 glVertex3fv(mv[mf->v1].co);
807 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
808 glVertex3fv(mv[mf->v2].co);
809 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
810 glVertex3fv(mv[mf->v3].co);
812 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
813 glVertex3fv(mv[mf->v4].co);
816 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
817 glNormal3sv(mv[mf->v1].no);
818 glVertex3fv(mv[mf->v1].co);
819 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
820 glNormal3sv(mv[mf->v2].no);
821 glVertex3fv(mv[mf->v2].co);
822 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
823 glNormal3sv(mv[mf->v3].no);
824 glVertex3fv(mv[mf->v3].co);
826 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
827 glNormal3sv(mv[mf->v4].no);
828 glVertex3fv(mv[mf->v4].co);
838 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
842 GPU_vertex_setup(dm);
843 GPU_normal_setup(dm);
844 if( useColors && mc )
846 if( !GPU_buffer_legacy(dm) ) {
847 glShadeModel(GL_SMOOTH);
848 for( i = 0; i < dm->drawObject->nelements/3; i++ ) {
849 int actualFace = dm->drawObject->faceRemap[i];
850 int drawSmooth = (mf[actualFace].flag & ME_SMOOTH);
853 orig = index[actualFace];
854 if(setDrawOptions && orig == ORIGINDEX_NONE)
863 if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) {
870 if( prevstate != state && prevstate == 1 ) {
871 if( i-prevstart > 0 ) {
872 glDrawArrays(GL_TRIANGLES,prevstart*3,(i-prevstart)*3);
879 glDrawArrays(GL_TRIANGLES,prevstart*3,dm->drawObject->nelements-prevstart*3);
881 glShadeModel(GL_FLAT);
887 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
889 cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
892 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
894 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
895 GPUVertexAttribs gattribs;
896 DMVertexAttribs attribs;
897 MVert *mvert = cddm->mvert;
898 MFace *mface = cddm->mface;
899 MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
900 float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
901 int a, b, dodraw, smoothnormal, matnr, new_matnr;
902 int transp, new_transp, orig_transp;
903 int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
908 transp = GPU_get_material_blend_mode();
909 orig_transp = transp;
911 glShadeModel(GL_SMOOTH);
913 if( GPU_buffer_legacy(dm) || setDrawOptions != 0 ) {
914 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
915 memset(&attribs, 0, sizeof(attribs));
919 for(a = 0; a < dm->numFaceData; a++, mface++) {
920 new_matnr = mface->mat_nr + 1;
922 if(new_matnr != matnr) {
925 dodraw = setMaterial(matnr = new_matnr, &gattribs);
927 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
935 else if(setDrawOptions) {
936 orig = (index)? index[a]: a;
938 if(orig == ORIGINDEX_NONE)
940 else if(!setDrawOptions(userData, orig))
945 new_transp = tf[a].transp;
947 if(new_transp != transp) {
950 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
951 GPU_set_material_blend_mode(orig_transp);
953 GPU_set_material_blend_mode(new_transp);
960 smoothnormal = (mface->flag & ME_SMOOTH);
964 glNormal3fv(nors[a]);
967 /* TODO ideally a normal layer should always be available */
970 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
972 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
978 #define PASSVERT(index, vert) { \
979 if(attribs.totorco) \
980 glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \
981 for(b = 0; b < attribs.tottface; b++) { \
982 MTFace *tf = &attribs.tface[b].array[a]; \
983 glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \
985 for(b = 0; b < attribs.totmcol; b++) { \
986 MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \
988 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \
989 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \
991 if(attribs.tottang) { \
992 float *tang = attribs.tang.array[a*4 + vert]; \
993 glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \
996 glNormal3sv(mvert[index].no); \
997 glVertex3fv(mvert[index].co); \
1000 PASSVERT(mface->v1, 0);
1001 PASSVERT(mface->v2, 1);
1002 PASSVERT(mface->v3, 2);
1004 PASSVERT(mface->v4, 3)
1006 PASSVERT(mface->v3, 2)
1013 GPUBuffer *buffer = 0;
1015 int numdata = 0, elementsize = 0, offset;
1016 int start = 0, numfaces = 0, prevdraw = 0, curface = 0;
1020 GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
1021 memset(&attribs, 0, sizeof(attribs));
1023 GPU_vertex_setup(dm);
1024 GPU_normal_setup(dm);
1026 if( !GPU_buffer_legacy(dm) ) {
1027 for( i = 0; i < dm->drawObject->nelements/3; i++ ) {
1029 a = dm->drawObject->faceRemap[i];
1032 new_matnr = mface->mat_nr + 1;
1034 if(new_matnr != matnr ) {
1035 numfaces = curface - start;
1036 if( numfaces > 0 ) {
1040 if( numdata != 0 ) {
1042 GPU_buffer_unlock(buffer);
1044 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1047 glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
1049 if( numdata != 0 ) {
1051 GPU_buffer_free(buffer,0);
1061 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1063 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1065 if(attribs.totorco) {
1066 datatypes[numdata].index = attribs.orco.glIndex;
1067 datatypes[numdata].size = 3;
1068 datatypes[numdata].type = GL_FLOAT;
1071 for(b = 0; b < attribs.tottface; b++) {
1072 datatypes[numdata].index = attribs.tface[b].glIndex;
1073 datatypes[numdata].size = 2;
1074 datatypes[numdata].type = GL_FLOAT;
1077 for(b = 0; b < attribs.totmcol; b++) {
1078 datatypes[numdata].index = attribs.mcol[b].glIndex;
1079 datatypes[numdata].size = 4;
1080 datatypes[numdata].type = GL_UNSIGNED_BYTE;
1083 if(attribs.tottang) {
1084 datatypes[numdata].index = attribs.tang.glIndex;
1085 datatypes[numdata].size = 3;
1086 datatypes[numdata].type = GL_FLOAT;
1089 if( numdata != 0 ) {
1090 elementsize = GPU_attrib_element_size( datatypes, numdata );
1091 buffer = GPU_buffer_alloc( elementsize*dm->drawObject->nelements, 0 );
1093 GPU_buffer_unbind();
1094 dm->drawObject->legacy = 1;
1097 varray = GPU_buffer_lock_stream(buffer);
1099 GPU_buffer_unbind();
1100 GPU_buffer_free(buffer, 0);
1101 dm->drawObject->legacy = 1;
1106 /* if the buffer was set, dont use it again.
1107 * prevdraw was assumed true but didnt run so set to false - [#21036] */
1118 new_transp = tf[a].transp;
1120 if(new_transp != transp) {
1121 numfaces = curface - start;
1122 if( numfaces > 0 ) {
1124 if( numdata != 0 ) {
1125 GPU_buffer_unlock(buffer);
1126 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1128 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1129 if( numdata != 0 ) {
1130 varray = GPU_buffer_lock_stream(buffer);
1136 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1137 GPU_set_material_blend_mode(orig_transp);
1139 GPU_set_material_blend_mode(new_transp);
1140 transp = new_transp;
1144 if( numdata != 0 ) {
1146 if(attribs.totorco) {
1147 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
1148 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
1149 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
1150 offset += sizeof(float)*3;
1152 for(b = 0; b < attribs.tottface; b++) {
1153 MTFace *tf = &attribs.tface[b].array[a];
1154 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
1155 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
1157 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
1158 offset += sizeof(float)*2;
1160 for(b = 0; b < attribs.totmcol; b++) {
1161 MCol *cp = &attribs.mcol[b].array[a*4 + 0];
1163 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1164 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1165 cp = &attribs.mcol[b].array[a*4 + 1];
1166 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1167 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1168 cp = &attribs.mcol[b].array[a*4 + 2];
1169 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1170 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1171 offset += sizeof(unsigned char)*4;
1173 if(attribs.tottang) {
1174 float *tang = attribs.tang.array[a*4 + 0];
1175 VECCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1176 tang = attribs.tang.array[a*4 + 1];
1177 VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1178 tang = attribs.tang.array[a*4 + 2];
1179 VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1180 offset += sizeof(float)*3;
1185 if( numdata != 0 ) {
1187 if(attribs.totorco) {
1188 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1189 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1190 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1191 offset += sizeof(float)*3;
1193 for(b = 0; b < attribs.tottface; b++) {
1194 MTFace *tf = &attribs.tface[b].array[a];
1195 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1196 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1197 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1198 offset += sizeof(float)*2;
1200 for(b = 0; b < attribs.totmcol; b++) {
1201 MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1203 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1204 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1205 cp = &attribs.mcol[b].array[a*4 + 3];
1206 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1207 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1208 cp = &attribs.mcol[b].array[a*4 + 0];
1209 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1210 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1211 offset += sizeof(unsigned char)*4;
1213 if(attribs.tottang) {
1214 float *tang = attribs.tang.array[a*4 + 2];
1215 VECCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1216 tang = attribs.tang.array[a*4 + 3];
1217 VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1218 tang = attribs.tang.array[a*4 + 0];
1219 VECCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1220 offset += sizeof(float)*3;
1227 numfaces = curface - start;
1228 if( numfaces > 0 ) {
1230 if( numdata != 0 ) {
1231 GPU_buffer_unlock(buffer);
1232 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1234 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1237 GPU_buffer_unbind();
1239 GPU_buffer_free( buffer, 0 );
1242 glShadeModel(GL_FLAT);
1245 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
1247 dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1250 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1252 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1253 MVert *vert = cddm->mvert;
1254 MEdge *edge = cddm->medge;
1255 int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1258 for(i = 0; i < dm->numEdgeData; i++, edge++) {
1261 if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1266 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1267 glVertex3fv(vert[edge->v1].co);
1268 glVertex3fv(vert[edge->v2].co);
1274 static void cdDM_foreachMappedVert(
1276 void (*func)(void *userData, int index, float *co,
1277 float *no_f, short *no_s),
1280 MVert *mv = CDDM_get_verts(dm);
1281 int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1283 for(i = 0; i < dm->numVertData; i++, mv++) {
1286 if(orig == ORIGINDEX_NONE) continue;
1287 func(userData, orig, mv->co, NULL, mv->no);
1290 func(userData, i, mv->co, NULL, mv->no);
1294 static void cdDM_foreachMappedEdge(
1296 void (*func)(void *userData, int index,
1297 float *v0co, float *v1co),
1300 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1301 MVert *mv = cddm->mvert;
1302 MEdge *med = cddm->medge;
1303 int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1305 for(i = 0; i < dm->numEdgeData; i++, med++) {
1308 if(orig == ORIGINDEX_NONE) continue;
1309 func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1312 func(userData, i, mv[med->v1].co, mv[med->v2].co);
1316 static void cdDM_foreachMappedFaceCenter(
1318 void (*func)(void *userData, int index,
1319 float *cent, float *no),
1322 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1323 MVert *mv = cddm->mvert;
1324 MFace *mf = cddm->mface;
1325 int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
1327 for(i = 0; i < dm->numFaceData; i++, mf++) {
1333 if(orig == ORIGINDEX_NONE) continue;
1338 VECCOPY(cent, mv[mf->v1].co);
1339 add_v3_v3v3(cent, cent, mv[mf->v2].co);
1340 add_v3_v3v3(cent, cent, mv[mf->v3].co);
1343 normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
1344 add_v3_v3v3(cent, cent, mv[mf->v4].co);
1345 mul_v3_fl(cent, 0.25f);
1347 normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
1348 mul_v3_fl(cent, 0.33333333333f);
1351 func(userData, orig, cent, no);
1355 static void cdDM_free_internal(CDDerivedMesh *cddm)
1357 if(cddm->pbvh) BLI_pbvh_free(cddm->pbvh);
1358 if(cddm->fmap) MEM_freeN(cddm->fmap);
1359 if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
1362 static void cdDM_release(DerivedMesh *dm)
1364 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1366 if (DM_release(dm)) {
1367 cdDM_free_internal(cddm);
1372 /**************** CDDM interface functions ****************/
1373 static CDDerivedMesh *cdDM_create(const char *desc)
1375 CDDerivedMesh *cddm;
1378 cddm = MEM_callocN(sizeof(*cddm), desc);
1381 dm->getMinMax = cdDM_getMinMax;
1383 dm->getNumVerts = cdDM_getNumVerts;
1384 dm->getNumFaces = cdDM_getNumFaces;
1385 dm->getNumEdges = cdDM_getNumEdges;
1387 dm->getVert = cdDM_getVert;
1388 dm->getEdge = cdDM_getEdge;
1389 dm->getFace = cdDM_getFace;
1390 dm->copyVertArray = cdDM_copyVertArray;
1391 dm->copyEdgeArray = cdDM_copyEdgeArray;
1392 dm->copyFaceArray = cdDM_copyFaceArray;
1393 dm->getVertData = DM_get_vert_data;
1394 dm->getEdgeData = DM_get_edge_data;
1395 dm->getFaceData = DM_get_face_data;
1396 dm->getVertDataArray = DM_get_vert_data_layer;
1397 dm->getEdgeDataArray = DM_get_edge_data_layer;
1398 dm->getFaceDataArray = DM_get_face_data_layer;
1400 dm->getVertCos = cdDM_getVertCos;
1401 dm->getVertCo = cdDM_getVertCo;
1402 dm->getVertNo = cdDM_getVertNo;
1404 dm->getPBVH = cdDM_getPBVH;
1405 dm->getFaceMap = cdDM_getFaceMap;
1407 dm->drawVerts = cdDM_drawVerts;
1409 dm->drawUVEdges = cdDM_drawUVEdges;
1410 dm->drawEdges = cdDM_drawEdges;
1411 dm->drawLooseEdges = cdDM_drawLooseEdges;
1412 dm->drawMappedEdges = cdDM_drawMappedEdges;
1414 dm->drawFacesSolid = cdDM_drawFacesSolid;
1415 dm->drawFacesColored = cdDM_drawFacesColored;
1416 dm->drawFacesTex = cdDM_drawFacesTex;
1417 dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1418 dm->drawMappedFaces = cdDM_drawMappedFaces;
1419 dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1420 dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1422 dm->foreachMappedVert = cdDM_foreachMappedVert;
1423 dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1424 dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1426 dm->release = cdDM_release;
1431 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
1433 CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1434 DerivedMesh *dm = &cddm->dm;
1436 DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1438 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1439 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1440 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1442 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1443 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1444 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1446 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1447 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1448 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1453 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
1455 CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1456 DerivedMesh *dm = &cddm->dm;
1457 CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1460 /* this does a referenced copy, with an exception for fluidsim */
1462 DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface);
1464 dm->deformedOnly = 1;
1466 alloctype= CD_REFERENCE;
1468 CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1470 CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1472 CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
1475 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1476 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1477 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1482 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
1484 DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1485 BLI_countlist(&em->edges),
1486 BLI_countlist(&em->faces));
1487 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1491 MVert *mvert = cddm->mvert;
1492 MEdge *medge = cddm->medge;
1493 MFace *mface = cddm->mface;
1496 dm->deformedOnly = 1;
1498 CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1499 CD_CALLOC, dm->numVertData);
1500 /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1501 CD_CALLOC, dm->numEdgeData); */
1502 CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1503 CD_CALLOC, dm->numFaceData);
1505 /* set eve->hash to vert index */
1506 for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1509 /* Need to be able to mark loose edges */
1510 for(eed = em->edges.first; eed; eed = eed->next) {
1513 for(efa = em->faces.first; efa; efa = efa->next) {
1517 if(efa->e4) efa->e4->f2 = 1;
1520 index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1521 for(i = 0, eve = em->verts.first; i < dm->numVertData;
1522 i++, eve = eve->next, index++) {
1523 MVert *mv = &mvert[i];
1525 VECCOPY(mv->co, eve->co);
1527 mv->no[0] = eve->no[0] * 32767.0;
1528 mv->no[1] = eve->no[1] * 32767.0;
1529 mv->no[2] = eve->no[2] * 32767.0;
1530 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1537 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1540 index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1541 for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1542 i++, eed = eed->next, index++) {
1543 MEdge *med = &medge[i];
1545 med->v1 = eed->v1->tmp.l;
1546 med->v2 = eed->v2->tmp.l;
1547 med->crease = (unsigned char) (eed->crease * 255.0f);
1548 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1549 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1551 if(eed->seam) med->flag |= ME_SEAM;
1552 if(eed->sharp) med->flag |= ME_SHARP;
1553 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1557 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1560 index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
1561 for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1562 i++, efa = efa->next, index++) {
1563 MFace *mf = &mface[i];
1565 mf->v1 = efa->v1->tmp.l;
1566 mf->v2 = efa->v2->tmp.l;
1567 mf->v3 = efa->v3->tmp.l;
1568 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1569 mf->mat_nr = efa->mat_nr;
1570 mf->flag = efa->flag;
1574 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1575 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1581 DerivedMesh *CDDM_from_curve(Object *ob)
1583 return CDDM_from_curve_customDB(ob, &((Curve *)ob->data)->disp);
1586 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
1589 CDDerivedMesh *cddm;
1593 int totvert, totedge, totface;
1595 if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
1596 &totedge, &allface, &totface) != 0) {
1597 /* Error initializing mdata. This often happens when curve is empty */
1598 return CDDM_new(0, 0, 0);
1601 dm = CDDM_new(totvert, totedge, totface);
1602 dm->deformedOnly = 1;
1604 cddm = (CDDerivedMesh*)dm;
1606 memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
1607 memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
1608 memcpy(cddm->mface, allface, totface*sizeof(MFace));
1617 DerivedMesh *CDDM_copy(DerivedMesh *source)
1619 CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
1620 DerivedMesh *dm = &cddm->dm;
1621 int numVerts = source->numVertData;
1622 int numEdges = source->numEdgeData;
1623 int numFaces = source->numFaceData;
1625 /* ensure these are created if they are made on demand */
1626 source->getVertDataArray(source, CD_ORIGINDEX);
1627 source->getEdgeDataArray(source, CD_ORIGINDEX);
1628 source->getFaceDataArray(source, CD_ORIGINDEX);
1630 /* this initializes dm, and copies all non mvert/medge/mface layers */
1631 DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1632 dm->deformedOnly = source->deformedOnly;
1634 CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
1635 CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
1636 CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
1638 /* now add mvert/medge/mface layers */
1639 cddm->mvert = source->dupVertArray(source);
1640 cddm->medge = source->dupEdgeArray(source);
1641 cddm->mface = source->dupFaceArray(source);
1643 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
1644 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
1645 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
1650 DerivedMesh *CDDM_from_template(DerivedMesh *source,
1651 int numVerts, int numEdges, int numFaces)
1653 CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
1654 DerivedMesh *dm = &cddm->dm;
1656 /* this does a copy of all non mvert/medge/mface layers */
1657 DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1659 /* now add mvert/medge/mface layers */
1660 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1661 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1662 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1664 if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
1665 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1666 if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX))
1667 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1668 if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))
1669 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1671 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1672 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1673 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1678 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
1680 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1684 /* this will just return the pointer if it wasn't a referenced layer */
1685 vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1688 for(i = 0; i < dm->numVertData; ++i, ++vert)
1689 VECCOPY(vert->co, vertCoords[i]);
1692 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
1694 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1698 /* this will just return the pointer if it wasn't a referenced layer */
1699 vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1702 for(i = 0; i < dm->numVertData; ++i, ++vert)
1703 VECCOPY(vert->no, vertNormals[i]);
1706 /* adapted from mesh_calc_normals */
1707 void CDDM_calc_normals(DerivedMesh *dm)
1709 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1710 float (*temp_nors)[3];
1711 float (*face_nors)[3];
1713 int numVerts = dm->numVertData;
1714 int numFaces = dm->numFaceData;
1718 if(numVerts == 0) return;
1720 temp_nors = MEM_callocN(numVerts * sizeof(*temp_nors),
1721 "CDDM_calc_normals temp_nors");
1723 /* we don't want to overwrite any referenced layers */
1724 mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1727 /* make a face normal layer if not present */
1728 face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
1730 face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
1731 NULL, dm->numFaceData);
1733 /* calculate face normals and add to vertex normals */
1734 mf = CDDM_get_faces(dm);
1735 for(i = 0; i < numFaces; i++, mf++) {
1736 float *f_no = face_nors[i];
1739 normal_quad_v3( f_no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
1741 normal_tri_v3( f_no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
1743 add_v3_v3v3(temp_nors[mf->v1], temp_nors[mf->v1], f_no);
1744 add_v3_v3v3(temp_nors[mf->v2], temp_nors[mf->v2], f_no);
1745 add_v3_v3v3(temp_nors[mf->v3], temp_nors[mf->v3], f_no);
1747 add_v3_v3v3(temp_nors[mf->v4], temp_nors[mf->v4], f_no);
1750 /* normalize vertex normals and assign */
1751 for(i = 0; i < numVerts; i++, mv++) {
1752 float *no = temp_nors[i];
1754 if (normalize_v3(no) == 0.0) {
1755 VECCOPY(no, mv->co);
1759 mv->no[0] = (short)(no[0] * 32767.0);
1760 mv->no[1] = (short)(no[1] * 32767.0);
1761 mv->no[2] = (short)(no[2] * 32767.0);
1764 MEM_freeN(temp_nors);
1767 void CDDM_calc_edges(DerivedMesh *dm)
1769 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1770 CustomData edgeData;
1771 EdgeHashIterator *ehi;
1772 MFace *mf = cddm->mface;
1774 EdgeHash *eh = BLI_edgehash_new();
1775 int i, *index, numEdges, maxFaces = dm->numFaceData;
1777 for (i = 0; i < maxFaces; i++, mf++) {
1778 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
1779 BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
1780 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
1781 BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
1784 if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
1785 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
1786 if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
1787 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
1789 if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
1790 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
1794 numEdges = BLI_edgehash_size(eh);
1796 /* write new edges into a temporary CustomData */
1797 memset(&edgeData, 0, sizeof(edgeData));
1798 CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1799 CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1801 ehi = BLI_edgehashIterator_new(eh);
1802 med = CustomData_get_layer(&edgeData, CD_MEDGE);
1803 index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
1804 for(i = 0; !BLI_edgehashIterator_isDone(ehi);
1805 BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
1806 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
1808 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1809 *index = ORIGINDEX_NONE;
1811 BLI_edgehashIterator_free(ehi);
1813 /* free old CustomData and assign new one */
1814 CustomData_free(&dm->edgeData, dm->numEdgeData);
1815 dm->edgeData = edgeData;
1816 dm->numEdgeData = numEdges;
1818 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1820 BLI_edgehash_free(eh, NULL);
1823 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
1825 if (numVerts < dm->numVertData)
1826 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
1828 dm->numVertData = numVerts;
1831 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
1833 if (numEdges < dm->numEdgeData)
1834 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
1836 dm->numEdgeData = numEdges;
1839 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
1841 if (numFaces < dm->numFaceData)
1842 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
1844 dm->numFaceData = numFaces;
1847 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
1849 return &((CDDerivedMesh*)dm)->mvert[index];
1852 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
1854 return &((CDDerivedMesh*)dm)->medge[index];
1857 MFace *CDDM_get_face(DerivedMesh *dm, int index)
1859 return &((CDDerivedMesh*)dm)->mface[index];
1862 MVert *CDDM_get_verts(DerivedMesh *dm)
1864 return ((CDDerivedMesh*)dm)->mvert;
1867 MEdge *CDDM_get_edges(DerivedMesh *dm)
1869 return ((CDDerivedMesh*)dm)->medge;
1872 MFace *CDDM_get_faces(DerivedMesh *dm)
1874 return ((CDDerivedMesh*)dm)->mface;