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 /** \file blender/blenkernel/intern/cdderivedmesh.c
40 /* TODO maybe BIF_gl.h should include string.h? */
44 #include "BLI_blenlib.h"
45 #include "BLI_edgehash.h"
46 #include "BLI_editVert.h"
49 #include "BLI_utildefines.h"
51 #include "BKE_cdderivedmesh.h"
52 #include "BKE_global.h"
54 #include "BKE_paint.h"
57 #include "DNA_meshdata_types.h"
58 #include "DNA_object_types.h"
59 #include "DNA_curve_types.h" /* for Curve */
61 #include "MEM_guardedalloc.h"
63 #include "GPU_buffers.h"
65 #include "GPU_extensions.h"
66 #include "GPU_material.h"
75 /* these point to data in the DerivedMesh custom data layers,
76 they are only here for efficiency and convenience **/
85 /* Mesh connectivity */
86 struct ListBase *fmap;
87 struct IndexNode *fmap_mem;
90 /**************** DerivedMesh interface functions ****************/
91 static int cdDM_getNumVerts(DerivedMesh *dm)
93 return dm->numVertData;
96 static int cdDM_getNumEdges(DerivedMesh *dm)
98 return dm->numEdgeData;
101 static int cdDM_getNumFaces(DerivedMesh *dm)
103 return dm->numFaceData;
106 static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
108 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
109 *vert_r = cddm->mvert[index];
112 static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
114 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
115 *edge_r = cddm->medge[index];
118 static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
120 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
121 *face_r = cddm->mface[index];
124 static void cdDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
126 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
127 memcpy(vert_r, cddm->mvert, sizeof(*vert_r) * dm->numVertData);
130 static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
132 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
133 memcpy(edge_r, cddm->medge, sizeof(*edge_r) * dm->numEdgeData);
136 static void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
138 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
139 memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData);
142 static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
144 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
147 if (dm->numVertData) {
148 for (i=0; i<dm->numVertData; i++) {
149 DO_MINMAX(cddm->mvert[i].co, min_r, max_r);
152 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
156 static void cdDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
158 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
160 VECCOPY(co_r, cddm->mvert[index].co);
163 static void cdDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
165 MVert *mv = CDDM_get_verts(dm);
168 for(i = 0; i < dm->numVertData; i++, mv++)
169 VECCOPY(cos_r[i], mv->co);
172 static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
174 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
175 normal_short_to_float_v3(no_r, cddm->mvert[index].no);
178 static ListBase *cdDM_getFaceMap(Object *ob, DerivedMesh *dm)
180 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
182 if(!cddm->fmap && ob->type == OB_MESH) {
185 create_vert_face_map(&cddm->fmap, &cddm->fmap_mem, me->mface,
186 me->totvert, me->totface);
192 static int can_pbvh_draw(Object *ob, DerivedMesh *dm)
194 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
198 /* active modifiers means extra deformation, which can't be handled correct
199 on bith of PBVH and sculpt "layer" levels, so use PBVH only for internal brush
200 stuff and show final DerivedMesh so user would see actual object shape */
201 deformed|= ob->sculpt->modifiers_active;
203 /* as in case with modifiers, we can't synchronize deformation made against
204 PBVH and non-locked keyblock, so also use PBVH only for brushes and
205 final DM to give final result to user */
206 deformed|= ob->sculpt->kb && (ob->shapeflag&OB_SHAPE_LOCK) == 0;
211 return (cddm->mvert == me->mvert) || ob->sculpt->kb;
214 static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
216 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
225 if(ob->sculpt->pbvh) {
226 cddm->pbvh= ob->sculpt->pbvh;
227 cddm->pbvh_draw = can_pbvh_draw(ob, dm);
230 /* always build pbvh from original mesh, and only use it for drawing if
231 this derivedmesh is just original mesh. it's the multires subsurf dm
232 that this is actually for, to support a pbvh on a modified mesh */
233 if(!cddm->pbvh && ob->type == OB_MESH) {
235 cddm->pbvh = BLI_pbvh_new();
236 cddm->pbvh_draw = can_pbvh_draw(ob, dm);
237 BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
238 me->totface, me->totvert);
240 if(ob->sculpt->modifiers_active) {
244 totvert= dm->getNumVerts(dm);
245 vertCos= MEM_callocN(3*totvert*sizeof(float), "cdDM_getPBVH vertCos");
246 dm->getVertCos(dm, vertCos);
247 BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos);
255 /* update vertex normals so that drawing smooth faces works during sculpt
256 TODO: proper fix is to support the pbvh in all drawing modes */
257 static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
259 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
260 float (*face_nors)[3];
262 if(!cddm->pbvh || !cddm->pbvh_draw || !dm->numFaceData)
265 face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
267 BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
270 static void cdDM_drawVerts(DerivedMesh *dm)
272 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
273 MVert *mv = cddm->mvert;
276 if( GPU_buffer_legacy(dm) ) {
278 for(i = 0; i < dm->numVertData; i++, mv++)
282 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
283 GPU_vertex_setup(dm);
284 if( !GPU_buffer_legacy(dm) ) {
285 if(dm->drawObject->nelements) glDrawArrays(GL_POINTS,0, dm->drawObject->nelements);
286 else glDrawArrays(GL_POINTS,0, dm->drawObject->nlooseverts);
292 static void cdDM_drawUVEdges(DerivedMesh *dm)
294 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
295 MFace *mf = cddm->mface;
296 MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
300 if( GPU_buffer_legacy(dm) ) {
302 for(i = 0; i < dm->numFaceData; i++, mf++, tf++) {
303 if(!(mf->flag&ME_HIDE)) {
304 glVertex2fv(tf->uv[0]);
305 glVertex2fv(tf->uv[1]);
307 glVertex2fv(tf->uv[1]);
308 glVertex2fv(tf->uv[2]);
311 glVertex2fv(tf->uv[2]);
312 glVertex2fv(tf->uv[0]);
314 glVertex2fv(tf->uv[2]);
315 glVertex2fv(tf->uv[3]);
317 glVertex2fv(tf->uv[3]);
318 glVertex2fv(tf->uv[0]);
330 GPU_uvedge_setup(dm);
331 if( !GPU_buffer_legacy(dm) ) {
332 for(i = 0; i < dm->numFaceData; i++, mf++) {
333 if(!(mf->flag&ME_HIDE)) {
339 if( prevdraw != draw ) {
340 if( prevdraw > 0 && (curpos-prevstart) > 0) {
341 glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
353 if( prevdraw > 0 && (curpos-prevstart) > 0 ) {
354 glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
362 static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges)
364 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
365 MVert *mvert = cddm->mvert;
366 MEdge *medge = cddm->medge;
369 if( GPU_buffer_legacy(dm) ) {
370 DEBUG_VBO( "Using legacy code. cdDM_drawEdges\n" );
372 for(i = 0; i < dm->numEdgeData; i++, medge++) {
373 if((drawAllEdges || (medge->flag&ME_EDGEDRAW))
374 && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
375 glVertex3fv(mvert[medge->v1].co);
376 glVertex3fv(mvert[medge->v2].co);
381 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
387 if( !GPU_buffer_legacy(dm) ) {
388 for(i = 0; i < dm->numEdgeData; i++, medge++) {
389 if((drawAllEdges || (medge->flag&ME_EDGEDRAW))
390 && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
396 if( prevdraw != draw ) {
397 if( prevdraw > 0 && (i-prevstart) > 0 ) {
398 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 );
404 if( prevdraw > 0 && (i-prevstart) > 0 ) {
405 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 );
412 static void cdDM_drawLooseEdges(DerivedMesh *dm)
414 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
415 MVert *mvert = cddm->mvert;
416 MEdge *medge = cddm->medge;
419 if( GPU_buffer_legacy(dm) ) {
420 DEBUG_VBO( "Using legacy code. cdDM_drawLooseEdges\n" );
422 for(i = 0; i < dm->numEdgeData; i++, medge++) {
423 if(medge->flag&ME_LOOSEEDGE) {
424 glVertex3fv(mvert[medge->v1].co);
425 glVertex3fv(mvert[medge->v2].co);
430 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
436 if( !GPU_buffer_legacy(dm) ) {
437 for(i = 0; i < dm->numEdgeData; i++, medge++) {
438 if(medge->flag&ME_LOOSEEDGE) {
444 if( prevdraw != draw ) {
445 if( prevdraw > 0 && (i-prevstart) > 0) {
446 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 );
452 if( prevdraw > 0 && (i-prevstart) > 0 ) {
453 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 );
460 static void cdDM_drawFacesSolid(DerivedMesh *dm,
461 float (*partial_redraw_planes)[4],
462 int UNUSED(fast), int (*setMaterial)(int, void *attribs))
464 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
465 MVert *mvert = cddm->mvert;
466 MFace *mface = cddm->mface;
467 float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
468 int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
470 #define PASSVERT(index) { \
471 if(shademodel == GL_SMOOTH) { \
472 short *no = mvert[index].no; \
475 glVertex3fv(mvert[index].co); \
478 if(cddm->pbvh && cddm->pbvh_draw) {
479 if(dm->numFaceData) {
480 float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
482 /* should be per face */
483 if(!setMaterial(mface->mat_nr+1, NULL))
486 glShadeModel((mface->flag & ME_SMOOTH)? GL_SMOOTH: GL_FLAT);
487 BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors, (mface->flag & ME_SMOOTH));
488 glShadeModel(GL_FLAT);
494 if( GPU_buffer_legacy(dm) ) {
495 DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" );
496 glBegin(glmode = GL_QUADS);
497 for(a = 0; a < dm->numFaceData; a++, mface++) {
498 int new_glmode, new_matnr, new_shademodel;
500 new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
501 new_matnr = mface->mat_nr + 1;
502 new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
504 if(new_glmode != glmode || new_matnr != matnr
505 || new_shademodel != shademodel) {
508 drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
510 glShadeModel(shademodel = new_shademodel);
511 glBegin(glmode = new_glmode);
515 if(shademodel == GL_FLAT) {
520 /* TODO make this better (cache facenormals as layer?) */
523 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
525 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
543 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
544 GPU_vertex_setup( dm );
545 GPU_normal_setup( dm );
546 if( !GPU_buffer_legacy(dm) ) {
547 glShadeModel(GL_SMOOTH);
548 for( a = 0; a < dm->drawObject->nmaterials; a++ ) {
549 if( setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL) )
550 glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start, dm->drawObject->materials[a].end-dm->drawObject->materials[a].start);
553 GPU_buffer_unbind( );
557 glShadeModel(GL_FLAT);
560 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
562 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
564 unsigned char *cp1, *cp2;
565 MVert *mvert = cddm->mvert;
566 MFace *mface = cddm->mface;
576 /* there's a conflict here... twosided colors versus culling...? */
577 /* defined by history, only texture faces have culling option */
578 /* we need that as mesh option builtin, next to double sided lighting */
580 glEnable(GL_CULL_FACE);
583 cdDM_update_normals_from_pbvh(dm);
585 if( GPU_buffer_legacy(dm) ) {
586 DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" );
587 glShadeModel(GL_SMOOTH);
588 glBegin(glmode = GL_QUADS);
589 for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
590 int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
592 if(new_glmode != glmode) {
594 glBegin(glmode = new_glmode);
598 glVertex3fv(mvert[mface->v1].co);
600 glVertex3fv(mvert[mface->v2].co);
602 glVertex3fv(mvert[mface->v3].co);
605 glVertex3fv(mvert[mface->v4].co);
610 glVertex3fv(mvert[mface->v3].co );
612 glVertex3fv(mvert[mface->v2].co );
614 glVertex3fv(mvert[mface->v1].co );
617 glVertex3fv(mvert[mface->v4].co );
624 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
625 GPU_color4_upload(dm,cp1);
626 GPU_vertex_setup(dm);
628 if( !GPU_buffer_legacy(dm) ) {
629 glShadeModel(GL_SMOOTH);
630 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
633 GPU_color4_upload(dm,cp2);
635 glCullFace(GL_FRONT);
636 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
643 glShadeModel(GL_FLAT);
644 glDisable(GL_CULL_FACE);
647 static void cdDM_drawFacesTex_common(DerivedMesh *dm,
648 int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
649 int (*drawParamsMapped)(void *userData, int index),
652 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
653 MVert *mv = cddm->mvert;
654 MFace *mf = DM_get_face_data_layer(dm, CD_MFACE);
655 MCol *realcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL);
656 float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
657 MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
658 int i, j, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
659 int startFace = 0, lastFlag = 0xdeadbeef;
660 MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
662 mcol = dm->getFaceDataArray(dm, CD_MCOL);
664 cdDM_update_normals_from_pbvh(dm);
666 if( GPU_buffer_legacy(dm) ) {
667 DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
668 for(i = 0; i < dm->numFaceData; i++, mf++) {
671 unsigned char *cp = NULL;
674 flag = drawParams(tf? &tf[i]: NULL, mcol? &mcol[i*4]: NULL, mf->mat_nr);
679 if(orig == ORIGINDEX_NONE) { if(nors) nors += 3; continue; }
680 if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
681 else { if(nors) nors += 3; continue; }
684 if(drawParamsMapped) flag = drawParamsMapped(userData, i);
685 else { if(nors) nors += 3; continue; }
690 cp= (unsigned char*) &mcol[i*4];
692 if(!(mf->flag&ME_SMOOTH)) {
699 normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
701 normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
707 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
708 if(tf) glTexCoord2fv(tf[i].uv[0]);
709 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
711 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
712 glVertex3fv(mvert->co);
714 if(tf) glTexCoord2fv(tf[i].uv[1]);
715 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
717 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
718 glVertex3fv(mvert->co);
720 if(tf) glTexCoord2fv(tf[i].uv[2]);
721 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
723 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
724 glVertex3fv(mvert->co);
727 if(tf) glTexCoord2fv(tf[i].uv[3]);
728 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
730 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
731 glVertex3fv(mvert->co);
738 } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
743 GPU_vertex_setup( dm );
744 GPU_normal_setup( dm );
747 /*if( realcol && dm->drawObject->colType == CD_TEXTURE_MCOL ) {
749 } else if( mcol && dm->drawObject->colType == CD_MCOL ) {
754 unsigned char *colors = MEM_mallocN(dm->getNumFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
755 for( i=0; i < dm->getNumFaces(dm); i++ ) {
756 for( j=0; j < 4; j++ ) {
757 colors[i*12+j*3] = col[i*4+j].r;
758 colors[i*12+j*3+1] = col[i*4+j].g;
759 colors[i*12+j*3+2] = col[i*4+j].b;
762 GPU_color3_upload(dm,colors);
765 dm->drawObject->colType = CD_TEXTURE_MCOL;
767 dm->drawObject->colType = CD_MCOL;
769 GPU_color_setup( dm );
772 if( !GPU_buffer_legacy(dm) ) {
773 /* warning!, this logic is incorrect, see bug [#27175]
774 * firstly, there are no checks for changes in context, such as texface image.
775 * secondly, drawParams() sets the GL context, so checking if there is a change
776 * from lastFlag is too late once glDrawArrays() runs, since drawing the arrays
777 * will use the modified, OpenGL settings.
779 * However its tricky to fix this without duplicating the internal logic
780 * of drawParams(), perhaps we need an argument like...
781 * drawParams(..., keep_gl_state_but_return_when_changed) ?.
783 * We could also just disable VBO's here, since texface may be deprecated - campbell.
786 glShadeModel( GL_SMOOTH );
788 for(i = 0; i < dm->drawObject->nelements/3; i++) {
789 int actualFace = dm->drawObject->faceRemap[i];
793 flag = drawParams(tf? &tf[actualFace]: NULL, mcol? &mcol[actualFace*4]: NULL, mf[actualFace].mat_nr);
797 orig = index[actualFace];
798 if(orig == ORIGINDEX_NONE) continue;
800 flag = drawParamsMapped(userData, orig);
804 flag = drawParamsMapped(userData, actualFace);
806 if( flag != lastFlag ) {
807 if( startFace < i ) {
808 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
809 if (lastFlag==1 && col)
813 glDrawArrays(GL_TRIANGLES,startFace*3,(i-startFace)*3);
820 if( startFace < dm->drawObject->nelements/3 ) {
821 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
822 if (lastFlag==1 && col)
826 glDrawArrays(GL_TRIANGLES,startFace*3,dm->drawObject->nelements-startFace*3);
832 glShadeModel( GL_FLAT );
836 static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
838 cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
841 static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs))
843 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
844 MVert *mv = cddm->mvert;
845 MFace *mf = cddm->mface;
847 float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
848 int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
850 mc = DM_get_face_data_layer(dm, CD_ID_MCOL);
852 mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
854 mc = DM_get_face_data_layer(dm, CD_MCOL);
856 cdDM_update_normals_from_pbvh(dm);
858 /* back-buffer always uses legacy since VBO's would need the
859 * color array temporarily overwritten for drawing, then reset. */
860 if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) {
861 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" );
862 for(i = 0; i < dm->numFaceData; i++, mf++) {
863 int drawSmooth = (mf->flag & ME_SMOOTH);
866 orig= (index==NULL) ? i : *index++;
868 if(orig == ORIGINDEX_NONE)
869 draw= setMaterial(mf->mat_nr + 1, NULL);
870 else if (setDrawOptions != NULL)
871 draw= setDrawOptions(userData, orig, &drawSmooth);
874 unsigned char *cp = NULL;
877 cp = (unsigned char *)&mc[i * 4];
879 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
880 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
889 normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
891 normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
896 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
897 glVertex3fv(mv[mf->v1].co);
898 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
899 glVertex3fv(mv[mf->v2].co);
900 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
901 glVertex3fv(mv[mf->v3].co);
903 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
904 glVertex3fv(mv[mf->v4].co);
907 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
908 glNormal3sv(mv[mf->v1].no);
909 glVertex3fv(mv[mf->v1].co);
910 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
911 glNormal3sv(mv[mf->v2].no);
912 glVertex3fv(mv[mf->v2].co);
913 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
914 glNormal3sv(mv[mf->v3].no);
915 glVertex3fv(mv[mf->v3].co);
917 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
918 glNormal3sv(mv[mf->v4].no);
919 glVertex3fv(mv[mf->v4].co);
929 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
931 GPU_vertex_setup(dm);
932 GPU_normal_setup(dm);
933 if( useColors && mc )
935 if( !GPU_buffer_legacy(dm) ) {
936 int tottri = dm->drawObject->nelements/3;
937 glShadeModel(GL_SMOOTH);
940 /* avoid buffer problems in following code */
942 if(setDrawOptions == NULL) {
943 /* just draw the entire face array */
944 glDrawArrays(GL_TRIANGLES, 0, (tottri-1) * 3);
947 /* we need to check if the next material changes */
948 int next_actualFace= dm->drawObject->faceRemap[0];
950 for( i = 0; i < tottri; i++ ) {
951 //int actualFace = dm->drawObject->faceRemap[i];
952 int actualFace = next_actualFace;
953 MFace *mface= mf + actualFace;
954 int drawSmooth= (mface->flag & ME_SMOOTH);
958 next_actualFace= dm->drawObject->faceRemap[i+1];
960 orig= (index==NULL) ? actualFace : index[actualFace];
962 if(orig == ORIGINDEX_NONE)
963 draw= setMaterial(mface->mat_nr + 1, NULL);
964 else if (setDrawOptions != NULL)
965 draw= setDrawOptions(userData, orig, &drawSmooth);
967 /* Goal is to draw as long of a contiguous triangle
968 array as possible, so draw when we hit either an
969 invisible triangle or at the end of the array */
970 if(!draw || i == tottri - 1 || mf[actualFace].mat_nr != mf[next_actualFace].mat_nr) {
972 /* Add one to the length (via `draw')
973 if we're drawing at the end of the array */
974 glDrawArrays(GL_TRIANGLES,prevstart*3, (i-prevstart+draw)*3);
980 glShadeModel(GL_FLAT);
986 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
988 cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
991 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
993 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
994 GPUVertexAttribs gattribs;
995 DMVertexAttribs attribs;
996 MVert *mvert = cddm->mvert;
997 MFace *mface = cddm->mface;
998 MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
999 float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
1000 int a, b, dodraw, matnr, new_matnr;
1001 int transp, new_transp, orig_transp;
1002 int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
1004 cdDM_update_normals_from_pbvh(dm);
1008 transp = GPU_get_material_blend_mode();
1009 orig_transp = transp;
1011 glShadeModel(GL_SMOOTH);
1013 if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) {
1014 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
1015 memset(&attribs, 0, sizeof(attribs));
1019 for(a = 0; a < dm->numFaceData; a++, mface++) {
1020 const int smoothnormal = (mface->flag & ME_SMOOTH);
1021 new_matnr = mface->mat_nr + 1;
1023 if(new_matnr != matnr) {
1026 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1028 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1036 else if(setDrawOptions) {
1037 orig = (index)? index[a]: a;
1039 if(orig == ORIGINDEX_NONE) {
1040 /* since the material is set by setMaterial(), faces with no
1041 * origin can be assumed to be generated by a modifier */
1045 else if(!setDrawOptions(userData, orig))
1050 new_transp = tf[a].transp;
1052 if(new_transp != transp) {
1055 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1056 GPU_set_material_blend_mode(orig_transp);
1058 GPU_set_material_blend_mode(new_transp);
1059 transp = new_transp;
1067 glNormal3fv(nors[a]);
1070 /* TODO ideally a normal layer should always be available */
1073 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
1075 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
1081 #define PASSVERT(index, vert) { \
1082 if(attribs.totorco) \
1083 glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \
1084 for(b = 0; b < attribs.tottface; b++) { \
1085 MTFace *tf = &attribs.tface[b].array[a]; \
1086 glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \
1088 for(b = 0; b < attribs.totmcol; b++) { \
1089 MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \
1091 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \
1092 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \
1094 if(attribs.tottang) { \
1095 float *tang = attribs.tang.array[a*4 + vert]; \
1096 glVertexAttrib4fvARB(attribs.tang.glIndex, tang); \
1099 glNormal3sv(mvert[index].no); \
1100 glVertex3fv(mvert[index].co); \
1103 PASSVERT(mface->v1, 0);
1104 PASSVERT(mface->v2, 1);
1105 PASSVERT(mface->v3, 2);
1107 PASSVERT(mface->v4, 3)
1109 PASSVERT(mface->v3, 2)
1116 GPUBuffer *buffer = NULL;
1117 char *varray = NULL;
1118 int numdata = 0, elementsize = 0, offset;
1119 int start = 0, numfaces = 0, prevdraw = 0, curface = 0;
1123 GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
1124 memset(&attribs, 0, sizeof(attribs));
1126 GPU_vertex_setup(dm);
1127 GPU_normal_setup(dm);
1129 if( !GPU_buffer_legacy(dm) ) {
1130 for( i = 0; i < dm->drawObject->nelements/3; i++ ) {
1132 a = dm->drawObject->faceRemap[i];
1135 new_matnr = mface->mat_nr + 1;
1137 if(new_matnr != matnr ) {
1138 numfaces = curface - start;
1139 if( numfaces > 0 ) {
1143 if( numdata != 0 ) {
1145 GPU_buffer_unlock(buffer);
1147 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1150 glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
1152 if( numdata != 0 ) {
1154 GPU_buffer_free(buffer, NULL);
1164 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1166 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1168 if(attribs.totorco) {
1169 datatypes[numdata].index = attribs.orco.glIndex;
1170 datatypes[numdata].size = 3;
1171 datatypes[numdata].type = GL_FLOAT;
1174 for(b = 0; b < attribs.tottface; b++) {
1175 datatypes[numdata].index = attribs.tface[b].glIndex;
1176 datatypes[numdata].size = 2;
1177 datatypes[numdata].type = GL_FLOAT;
1180 for(b = 0; b < attribs.totmcol; b++) {
1181 datatypes[numdata].index = attribs.mcol[b].glIndex;
1182 datatypes[numdata].size = 4;
1183 datatypes[numdata].type = GL_UNSIGNED_BYTE;
1186 if(attribs.tottang) {
1187 datatypes[numdata].index = attribs.tang.glIndex;
1188 datatypes[numdata].size = 4;
1189 datatypes[numdata].type = GL_FLOAT;
1192 if( numdata != 0 ) {
1193 elementsize = GPU_attrib_element_size( datatypes, numdata );
1194 buffer = GPU_buffer_alloc( elementsize*dm->drawObject->nelements, NULL );
1195 if( buffer == NULL ) {
1196 GPU_buffer_unbind();
1197 dm->drawObject->legacy = 1;
1200 varray = GPU_buffer_lock_stream(buffer);
1201 if( varray == NULL ) {
1202 GPU_buffer_unbind();
1203 GPU_buffer_free(buffer, NULL);
1204 dm->drawObject->legacy = 1;
1209 /* if the buffer was set, dont use it again.
1210 * prevdraw was assumed true but didnt run so set to false - [#21036] */
1221 new_transp = tf[a].transp;
1223 if(new_transp != transp) {
1224 numfaces = curface - start;
1225 if( numfaces > 0 ) {
1227 if( numdata != 0 ) {
1228 GPU_buffer_unlock(buffer);
1229 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1231 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1232 if( numdata != 0 ) {
1233 varray = GPU_buffer_lock_stream(buffer);
1239 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1240 GPU_set_material_blend_mode(orig_transp);
1242 GPU_set_material_blend_mode(new_transp);
1243 transp = new_transp;
1247 if( numdata != 0 ) {
1249 if(attribs.totorco) {
1250 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
1251 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
1252 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
1253 offset += sizeof(float)*3;
1255 for(b = 0; b < attribs.tottface; b++) {
1256 MTFace *tf = &attribs.tface[b].array[a];
1257 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
1258 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
1260 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
1261 offset += sizeof(float)*2;
1263 for(b = 0; b < attribs.totmcol; b++) {
1264 MCol *cp = &attribs.mcol[b].array[a*4 + 0];
1266 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1267 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1268 cp = &attribs.mcol[b].array[a*4 + 1];
1269 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1270 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1271 cp = &attribs.mcol[b].array[a*4 + 2];
1272 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1273 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1274 offset += sizeof(unsigned char)*4;
1276 if(attribs.tottang) {
1277 float *tang = attribs.tang.array[a*4 + 0];
1278 QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1279 tang = attribs.tang.array[a*4 + 1];
1280 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1281 tang = attribs.tang.array[a*4 + 2];
1282 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1283 offset += sizeof(float)*4;
1288 if( numdata != 0 ) {
1290 if(attribs.totorco) {
1291 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1292 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1293 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1294 offset += sizeof(float)*3;
1296 for(b = 0; b < attribs.tottface; b++) {
1297 MTFace *tf = &attribs.tface[b].array[a];
1298 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1299 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1300 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1301 offset += sizeof(float)*2;
1303 for(b = 0; b < attribs.totmcol; b++) {
1304 MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1306 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1307 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1308 cp = &attribs.mcol[b].array[a*4 + 3];
1309 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1310 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1311 cp = &attribs.mcol[b].array[a*4 + 0];
1312 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1313 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1314 offset += sizeof(unsigned char)*4;
1316 if(attribs.tottang) {
1317 float *tang = attribs.tang.array[a*4 + 2];
1318 QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1319 tang = attribs.tang.array[a*4 + 3];
1320 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1321 tang = attribs.tang.array[a*4 + 0];
1322 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1323 offset += sizeof(float)*4;
1330 numfaces = curface - start;
1331 if( numfaces > 0 ) {
1333 if( numdata != 0 ) {
1334 GPU_buffer_unlock(buffer);
1335 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1337 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1340 GPU_buffer_unbind();
1342 GPU_buffer_free( buffer, NULL );
1345 glShadeModel(GL_FLAT);
1348 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
1350 dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1353 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1355 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1356 MVert *vert = cddm->mvert;
1357 MEdge *edge = cddm->medge;
1358 int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1361 for(i = 0; i < dm->numEdgeData; i++, edge++) {
1364 if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1369 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1370 glVertex3fv(vert[edge->v1].co);
1371 glVertex3fv(vert[edge->v2].co);
1377 static void cdDM_foreachMappedVert(
1379 void (*func)(void *userData, int index, float *co,
1380 float *no_f, short *no_s),
1383 MVert *mv = CDDM_get_verts(dm);
1384 int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1386 for(i = 0; i < dm->numVertData; i++, mv++) {
1389 if(orig == ORIGINDEX_NONE) continue;
1390 func(userData, orig, mv->co, NULL, mv->no);
1393 func(userData, i, mv->co, NULL, mv->no);
1397 static void cdDM_foreachMappedEdge(
1399 void (*func)(void *userData, int index,
1400 float *v0co, float *v1co),
1403 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1404 MVert *mv = cddm->mvert;
1405 MEdge *med = cddm->medge;
1406 int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1408 for(i = 0; i < dm->numEdgeData; i++, med++) {
1411 if(orig == ORIGINDEX_NONE) continue;
1412 func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1415 func(userData, i, mv[med->v1].co, mv[med->v2].co);
1419 static void cdDM_foreachMappedFaceCenter(
1421 void (*func)(void *userData, int index,
1422 float *cent, float *no),
1425 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1426 MVert *mv = cddm->mvert;
1427 MFace *mf = cddm->mface;
1428 int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
1430 for(i = 0; i < dm->numFaceData; i++, mf++) {
1436 if(orig == ORIGINDEX_NONE) continue;
1441 VECCOPY(cent, mv[mf->v1].co);
1442 add_v3_v3(cent, mv[mf->v2].co);
1443 add_v3_v3(cent, mv[mf->v3].co);
1446 normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
1447 add_v3_v3(cent, mv[mf->v4].co);
1448 mul_v3_fl(cent, 0.25f);
1450 normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
1451 mul_v3_fl(cent, 0.33333333333f);
1454 func(userData, orig, cent, no);
1458 static void cdDM_free_internal(CDDerivedMesh *cddm)
1460 if(cddm->fmap) MEM_freeN(cddm->fmap);
1461 if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
1464 static void cdDM_release(DerivedMesh *dm)
1466 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1468 if (DM_release(dm)) {
1469 cdDM_free_internal(cddm);
1474 /**************** CDDM interface functions ****************/
1475 static CDDerivedMesh *cdDM_create(const char *desc)
1477 CDDerivedMesh *cddm;
1480 cddm = MEM_callocN(sizeof(*cddm), desc);
1483 dm->getMinMax = cdDM_getMinMax;
1485 dm->getNumVerts = cdDM_getNumVerts;
1486 dm->getNumFaces = cdDM_getNumFaces;
1487 dm->getNumEdges = cdDM_getNumEdges;
1489 dm->getVert = cdDM_getVert;
1490 dm->getEdge = cdDM_getEdge;
1491 dm->getFace = cdDM_getFace;
1492 dm->copyVertArray = cdDM_copyVertArray;
1493 dm->copyEdgeArray = cdDM_copyEdgeArray;
1494 dm->copyFaceArray = cdDM_copyFaceArray;
1495 dm->getVertData = DM_get_vert_data;
1496 dm->getEdgeData = DM_get_edge_data;
1497 dm->getFaceData = DM_get_face_data;
1498 dm->getVertDataArray = DM_get_vert_data_layer;
1499 dm->getEdgeDataArray = DM_get_edge_data_layer;
1500 dm->getFaceDataArray = DM_get_face_data_layer;
1502 dm->getVertCos = cdDM_getVertCos;
1503 dm->getVertCo = cdDM_getVertCo;
1504 dm->getVertNo = cdDM_getVertNo;
1506 dm->getPBVH = cdDM_getPBVH;
1507 dm->getFaceMap = cdDM_getFaceMap;
1509 dm->drawVerts = cdDM_drawVerts;
1511 dm->drawUVEdges = cdDM_drawUVEdges;
1512 dm->drawEdges = cdDM_drawEdges;
1513 dm->drawLooseEdges = cdDM_drawLooseEdges;
1514 dm->drawMappedEdges = cdDM_drawMappedEdges;
1516 dm->drawFacesSolid = cdDM_drawFacesSolid;
1517 dm->drawFacesColored = cdDM_drawFacesColored;
1518 dm->drawFacesTex = cdDM_drawFacesTex;
1519 dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1520 dm->drawMappedFaces = cdDM_drawMappedFaces;
1521 dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1522 dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1524 dm->foreachMappedVert = cdDM_foreachMappedVert;
1525 dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1526 dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1528 dm->release = cdDM_release;
1533 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
1535 CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1536 DerivedMesh *dm = &cddm->dm;
1538 DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1540 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1541 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1542 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1544 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1545 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1546 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1548 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1549 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1550 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1555 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
1557 CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1558 DerivedMesh *dm = &cddm->dm;
1559 CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1562 /* this does a referenced copy, with an exception for fluidsim */
1564 DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface);
1566 dm->deformedOnly = 1;
1568 alloctype= CD_REFERENCE;
1570 CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1572 CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1574 CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
1577 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1578 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1579 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1584 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
1586 DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1587 BLI_countlist(&em->edges),
1588 BLI_countlist(&em->faces));
1589 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1593 MVert *mvert = cddm->mvert;
1594 MEdge *medge = cddm->medge;
1595 MFace *mface = cddm->mface;
1598 dm->deformedOnly = 1;
1600 CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1601 CD_CALLOC, dm->numVertData);
1602 /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1603 CD_CALLOC, dm->numEdgeData); */
1604 CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1605 CD_CALLOC, dm->numFaceData);
1607 /* set eve->hash to vert index */
1608 for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1611 /* Need to be able to mark loose edges */
1612 for(eed = em->edges.first; eed; eed = eed->next) {
1615 for(efa = em->faces.first; efa; efa = efa->next) {
1619 if(efa->e4) efa->e4->f2 = 1;
1622 index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1623 for(i = 0, eve = em->verts.first; i < dm->numVertData;
1624 i++, eve = eve->next, index++) {
1625 MVert *mv = &mvert[i];
1627 VECCOPY(mv->co, eve->co);
1629 normal_float_to_short_v3(mv->no, eve->no);
1630 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1636 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1639 index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1640 for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1641 i++, eed = eed->next, index++) {
1642 MEdge *med = &medge[i];
1644 med->v1 = eed->v1->tmp.l;
1645 med->v2 = eed->v2->tmp.l;
1646 med->crease = (unsigned char) (eed->crease * 255.0f);
1647 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1648 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1650 if(eed->seam) med->flag |= ME_SEAM;
1651 if(eed->sharp) med->flag |= ME_SHARP;
1652 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1656 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1659 index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
1660 for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1661 i++, efa = efa->next, index++) {
1662 MFace *mf = &mface[i];
1664 mf->v1 = efa->v1->tmp.l;
1665 mf->v2 = efa->v2->tmp.l;
1666 mf->v3 = efa->v3->tmp.l;
1667 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1668 mf->mat_nr = efa->mat_nr;
1669 mf->flag = efa->flag;
1673 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1674 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1680 DerivedMesh *CDDM_from_curve(Object *ob)
1682 return CDDM_from_curve_customDB(ob, &ob->disp);
1685 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
1688 CDDerivedMesh *cddm;
1692 int totvert, totedge, totface;
1694 if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
1695 &totedge, &allface, &totface) != 0) {
1696 /* Error initializing mdata. This often happens when curve is empty */
1697 return CDDM_new(0, 0, 0);
1700 dm = CDDM_new(totvert, totedge, totface);
1701 dm->deformedOnly = 1;
1703 cddm = (CDDerivedMesh*)dm;
1705 memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
1706 memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
1707 memcpy(cddm->mface, allface, totface*sizeof(MFace));
1716 DerivedMesh *CDDM_copy(DerivedMesh *source)
1718 CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
1719 DerivedMesh *dm = &cddm->dm;
1720 int numVerts = source->numVertData;
1721 int numEdges = source->numEdgeData;
1722 int numFaces = source->numFaceData;
1724 /* ensure these are created if they are made on demand */
1725 source->getVertDataArray(source, CD_ORIGINDEX);
1726 source->getEdgeDataArray(source, CD_ORIGINDEX);
1727 source->getFaceDataArray(source, CD_ORIGINDEX);
1729 /* this initializes dm, and copies all non mvert/medge/mface layers */
1730 DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1731 dm->deformedOnly = source->deformedOnly;
1733 CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
1734 CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
1735 CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
1737 /* now add mvert/medge/mface layers */
1738 cddm->mvert = source->dupVertArray(source);
1739 cddm->medge = source->dupEdgeArray(source);
1740 cddm->mface = source->dupFaceArray(source);
1742 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
1743 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
1744 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
1749 /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
1750 * relationship betwen mesh data this needs to be set by the caller. */
1751 DerivedMesh *CDDM_from_template(DerivedMesh *source,
1752 int numVerts, int numEdges, int numFaces)
1754 CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
1755 DerivedMesh *dm = &cddm->dm;
1757 /* ensure these are created if they are made on demand */
1758 source->getVertDataArray(source, CD_ORIGINDEX);
1759 source->getEdgeDataArray(source, CD_ORIGINDEX);
1760 source->getFaceDataArray(source, CD_ORIGINDEX);
1762 /* this does a copy of all non mvert/medge/mface layers */
1763 DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1765 /* now add mvert/medge/mface layers */
1766 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1767 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1768 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1770 if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
1771 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1772 if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX))
1773 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1774 if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))
1775 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1777 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1778 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1779 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1784 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
1786 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1790 /* this will just return the pointer if it wasn't a referenced layer */
1791 vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1794 for(i = 0; i < dm->numVertData; ++i, ++vert)
1795 VECCOPY(vert->co, vertCoords[i]);
1798 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
1800 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1804 /* this will just return the pointer if it wasn't a referenced layer */
1805 vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1808 for(i = 0; i < dm->numVertData; ++i, ++vert)
1809 VECCOPY(vert->no, vertNormals[i]);
1812 void CDDM_calc_normals(DerivedMesh *dm)
1814 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1815 float (*face_nors)[3];
1817 if(dm->numVertData == 0) return;
1819 /* we don't want to overwrite any referenced layers */
1820 cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1822 /* make a face normal layer if not present */
1823 face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
1825 face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
1826 NULL, dm->numFaceData);
1828 /* calculate face normals */
1829 mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_faces(dm), dm->numFaceData, face_nors);
1832 void CDDM_calc_edges(DerivedMesh *dm)
1834 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1835 CustomData edgeData;
1836 EdgeHashIterator *ehi;
1837 MFace *mf = cddm->mface;
1839 EdgeHash *eh = BLI_edgehash_new();
1840 int i, *index, numEdges, maxFaces = dm->numFaceData;
1842 for (i = 0; i < maxFaces; i++, mf++) {
1843 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
1844 BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
1845 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
1846 BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
1849 if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
1850 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
1851 if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
1852 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
1854 if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
1855 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
1859 numEdges = BLI_edgehash_size(eh);
1861 /* write new edges into a temporary CustomData */
1862 memset(&edgeData, 0, sizeof(edgeData));
1863 CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1864 CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1866 ehi = BLI_edgehashIterator_new(eh);
1867 med = CustomData_get_layer(&edgeData, CD_MEDGE);
1868 index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
1869 for(i = 0; !BLI_edgehashIterator_isDone(ehi);
1870 BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
1871 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
1873 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1874 *index = ORIGINDEX_NONE;
1876 BLI_edgehashIterator_free(ehi);
1878 /* free old CustomData and assign new one */
1879 CustomData_free(&dm->edgeData, dm->numEdgeData);
1880 dm->edgeData = edgeData;
1881 dm->numEdgeData = numEdges;
1883 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1885 BLI_edgehash_free(eh, NULL);
1888 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
1890 if (numVerts < dm->numVertData)
1891 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
1893 dm->numVertData = numVerts;
1896 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
1898 if (numEdges < dm->numEdgeData)
1899 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
1901 dm->numEdgeData = numEdges;
1904 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
1906 if (numFaces < dm->numFaceData)
1907 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
1909 dm->numFaceData = numFaces;
1912 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
1914 return &((CDDerivedMesh*)dm)->mvert[index];
1917 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
1919 return &((CDDerivedMesh*)dm)->medge[index];
1922 MFace *CDDM_get_face(DerivedMesh *dm, int index)
1924 return &((CDDerivedMesh*)dm)->mface[index];
1927 MVert *CDDM_get_verts(DerivedMesh *dm)
1929 return ((CDDerivedMesh*)dm)->mvert;
1932 MEdge *CDDM_get_edges(DerivedMesh *dm)
1934 return ((CDDerivedMesh*)dm)->medge;
1937 MFace *CDDM_get_faces(DerivedMesh *dm)
1939 return ((CDDerivedMesh*)dm)->mface;