2
* ***** BEGIN GPL LICENSE BLOCK *****
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software Foundation,
16
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
* The Original Code is Copyright (C) 2005 Blender Foundation.
19
* All rights reserved.
21
* The Original Code is: all of this file.
23
* Contributor(s): none yet.
25
* ***** END GPL LICENSE BLOCK *****
28
/** \file blender/blenkernel/intern/editderivedmesh.c
38
#include "BLI_utildefines.h"
39
#include "BLI_blenlib.h"
40
#include "BLI_edgehash.h"
44
#include "BKE_cdderivedmesh.h"
45
#include "BKE_global.h"
47
#include "BKE_paint.h"
50
#include "DNA_mesh_types.h"
51
#include "DNA_meshdata_types.h"
52
#include "DNA_object_types.h"
54
#include "MEM_guardedalloc.h"
56
#include "GPU_buffers.h"
58
#include "GPU_extensions.h"
59
#include "GPU_material.h"
62
#include "BKE_tessmesh.h"
63
#include "BLI_array.h"
64
#include "BLI_scanfill.h"
69
extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
72
BMEditMesh *BMEdit_Create(BMesh *bm, int do_tessellate)
74
BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), __func__);
78
BMEdit_RecalcTessellation(tm);
84
BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
86
BMEditMesh *tm2 = MEM_callocN(sizeof(BMEditMesh), __func__);
89
tm2->derivedCage = tm2->derivedFinal = NULL;
91
tm2->bm = BM_mesh_copy(tm->bm);
93
/* The tessellation is NOT calculated on the copy here,
94
* because currently all the callers of this function use
95
* it to make a backup copy of the BMEditMesh to restore
96
* it in the case of errors in an operation. For perf
97
* reasons, in that case it makes more sense to do the
98
* tessellation only when/if that copy ends up getting
100
tm2->looptris = NULL;
102
tm2->vert_index = NULL;
103
tm2->edge_index = NULL;
104
tm2->face_index = NULL;
109
static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm)
111
/* use this to avoid locking pthread for _every_ polygon
112
* and calling the fill function */
113
#define USE_TESSFACE_SPEEDUP
116
BMLoop *(*looptris)[3]= NULL;
117
BLI_array_declare(looptris);
123
ScanFillContext sf_ctx;
126
/* note, we could be clever and re-use this array but would need to ensure
127
* its realloced at some point, for now just free it */
128
if (tm->looptris) MEM_freeN(tm->looptris);
130
/* Use tm->tottri when set, this means no reallocs while transforming,
131
* (unless scanfill fails), otherwise... */
132
/* allocate the length of totfaces, avoid many small reallocs,
133
* if all faces are tri's it will be correct, quads == 2x allocs */
134
BLI_array_reserve(looptris, (tm->tottri && tm->tottri < bm->totface * 3) ? tm->tottri : bm->totface);
137
/* this means no reallocs for quad dominant models, for */
138
if ( (tm->looptris != NULL) &&
140
/* (totrti <= bm->totface * 2) would be fine for all quads,
141
* but in case there are some ngons, still re-use the array */
142
(tm->tottri <= bm->totface * 3))
144
looptris = tm->looptris;
147
if (tm->looptris) MEM_freeN(tm->looptris);
148
BLI_array_reserve(looptris, bm->totface);
153
f = BM_iter_new(&iter, bm, BM_FACES_OF_MESH, NULL);
154
for ( ; f; f=BM_iter_step(&iter)) {
155
/*don't consider two-edged faces*/
160
#ifdef USE_TESSFACE_SPEEDUP
162
/* no need to ensure the loop order, we know its ok */
164
else if (f->len == 3) {
165
BLI_array_growone(looptris);
166
l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
167
for (j=0; l; l=BM_iter_step(&liter), j++) {
172
else if (f->len == 4) {
174
BLI_array_growitems(looptris, 2);
176
l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
177
for (j=0; l; l=BM_iter_step(&liter), j++) {
181
looptris[i][0] = ltmp[0];
182
looptris[i][1] = ltmp[1];
183
looptris[i][2] = ltmp[2];
186
looptris[i][0] = ltmp[0];
187
looptris[i][1] = ltmp[2];
188
looptris[i][2] = ltmp[3];
192
#endif /* USE_TESSFACE_SPEEDUP */
195
ScanFillVert *v, *lastv=NULL, *firstv=NULL;
196
/* ScanFillEdge *e; */ /* UNUSED */
200
BLI_begin_edgefill(&sf_ctx);
202
l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
203
for (j=0; l; l=BM_iter_step(&liter), j++) {
205
BM_elem_index_set(l, j); /* set_loop */
207
v = BLI_addfillvert(&sf_ctx, l->v->co);
211
/* e = */ BLI_addfilledge(&sf_ctx, lastv, v);
215
if (firstv==NULL) firstv = v;
218
/*complete the loop*/
219
BLI_addfilledge(&sf_ctx, firstv, v);
221
totfilltri = BLI_edgefill_ex(&sf_ctx, FALSE, f->no);
222
BLI_array_growitems(looptris, totfilltri);
224
for (efa = sf_ctx.fillfacebase.first; efa; efa=efa->next) {
225
BMLoop *l1= efa->v1->tmp.p;
226
BMLoop *l2= efa->v2->tmp.p;
227
BMLoop *l3= efa->v3->tmp.p;
229
if (BM_elem_index_get(l1) > BM_elem_index_get(l2)) { SWAP(BMLoop*, l1, l2); }
230
if (BM_elem_index_get(l2) > BM_elem_index_get(l3)) { SWAP(BMLoop*, l2, l3); }
231
if (BM_elem_index_get(l1) > BM_elem_index_get(l2)) { SWAP(BMLoop*, l1, l2); }
239
BLI_end_edgefill(&sf_ctx);
244
tm->looptris = looptris;
246
#undef USE_TESSFACE_SPEEDUP
250
void BMEdit_RecalcTessellation(BMEditMesh *em)
252
BMEdit_RecalcTessellation_intern(em);
254
/* commented because editbmesh_build_data() ensures we get tessfaces */
256
if (em->derivedFinal && em->derivedFinal == em->derivedCage) {
257
if (em->derivedFinal->recalcTessellation)
258
em->derivedFinal->recalcTessellation(em->derivedFinal);
260
else if (em->derivedFinal) {
261
if (em->derivedCage->recalcTessellation)
262
em->derivedCage->recalcTessellation(em->derivedCage);
263
if (em->derivedFinal->recalcTessellation)
264
em->derivedFinal->recalcTessellation(em->derivedFinal);
269
void BMEdit_UpdateLinkedCustomData(BMEditMesh *em)
274
if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) {
275
act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY);
276
CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act);
278
act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY);
279
CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act);
281
act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY);
282
CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act);
284
act = CustomData_get_stencil_layer(&bm->pdata, CD_MTEXPOLY);
285
CustomData_set_layer_stencil(&bm->ldata, CD_MLOOPUV, act);
289
/*does not free the BMEditMesh struct itself*/
290
void BMEdit_Free(BMEditMesh *em)
292
if (em->derivedFinal) {
293
if (em->derivedFinal!=em->derivedCage) {
294
em->derivedFinal->needsFree= 1;
295
em->derivedFinal->release(em->derivedFinal);
297
em->derivedFinal= NULL;
299
if (em->derivedCage) {
300
em->derivedCage->needsFree= 1;
301
em->derivedCage->release(em->derivedCage);
302
em->derivedCage= NULL;
305
if (em->looptris) MEM_freeN(em->looptris);
307
if (em->vert_index) MEM_freeN(em->vert_index);
308
if (em->edge_index) MEM_freeN(em->edge_index);
309
if (em->face_index) MEM_freeN(em->face_index);
312
BM_mesh_free(em->bm);
318
* the bmesh derivedmesh exposes the mesh as triangles. it stores pointers
319
* to three loops per triangle. the derivedmesh stores a cache of tessellations
320
* for each face. this cache will smartly update as needed (though at first
321
* it'll simply be more brute force). keeping track of face/edge counts may
322
* be a small problbm.
324
* this won't be the most efficient thing, considering that internal edges and
325
* faces of tessellations are exposed. looking up an edge by index in particular
326
* is likely to be a little slow.
329
typedef struct EditDerivedBMesh {
335
float (*vertexCos)[3];
336
float (*vertexNos)[3];
339
/* private variables, for number of verts/edges/faces
340
* within the above hash/table members*/
344
static void emDM_calcNormals(DerivedMesh *UNUSED(dm))
346
/* Nothing to do: normals are already calculated and stored on the
347
* BMVerts and BMFaces */
350
static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
355
static void emDM_foreachMappedVert(
357
void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
360
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
365
eve = BM_iter_new(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
366
for (i=0; eve; i++, eve=BM_iter_step(&iter)) {
367
if (bmdm->vertexCos) {
368
func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL);
371
func(userData, i, eve->co, eve->no, NULL);
375
static void emDM_foreachMappedEdge(
377
void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
380
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
385
if (bmdm->vertexCos) {
387
BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
389
eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
390
for (i=0; eed; i++,eed=BM_iter_step(&iter))
392
bmdm->vertexCos[BM_elem_index_get(eed->v1)],
393
bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
396
eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
397
for (i=0; eed; i++,eed=BM_iter_step(&iter))
398
func(userData, i, eed->v1->co, eed->v2->co);
402
static void emDM_drawMappedEdges(
404
DMSetDrawOptions setDrawOptions,
407
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
412
if (bmdm->vertexCos) {
414
BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
417
eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
418
for (i=0; eed; i++,eed=BM_iter_step(&iter)) {
419
if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
420
glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
421
glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
428
eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
429
for (i=0; eed; i++,eed=BM_iter_step(&iter)) {
430
if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
431
glVertex3fv(eed->v1->co);
432
glVertex3fv(eed->v2->co);
438
static void emDM_drawEdges(
440
int UNUSED(drawLooseEdges),
441
int UNUSED(drawAllEdges))
443
emDM_drawMappedEdges(dm, NULL, NULL);
446
static void emDM_drawMappedEdgesInterp(
448
DMSetDrawOptions setDrawOptions,
449
DMSetDrawInterpOptions setDrawInterpOptions,
452
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
457
if (bmdm->vertexCos) {
459
BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
462
eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
463
for (i=0; eed; i++,eed=BM_iter_step(&iter)) {
464
if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
465
setDrawInterpOptions(userData, i, 0.0);
466
glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
467
setDrawInterpOptions(userData, i, 1.0);
468
glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
475
eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
476
for (i=0; eed; i++,eed=BM_iter_step(&iter)) {
477
if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
478
setDrawInterpOptions(userData, i, 0.0);
479
glVertex3fv(eed->v1->co);
480
setDrawInterpOptions(userData, i, 1.0);
481
glVertex3fv(eed->v2->co);
488
static void emDM_drawUVEdges(DerivedMesh *dm)
490
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
491
BMEditMesh *em = bmdm->tc;
496
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
499
MLoopUV *lastluv = NULL, *firstluv = NULL;
501
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
504
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
505
MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
509
glVertex2fv(luv->uv);
510
glVertex2fv(luv->uv);
519
glVertex2fv(lastluv->uv);
520
glVertex2fv(firstluv->uv);
526
static void emDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3], float (*vertexCos)[3])
534
/*simple (and stupid) median (average) based method :/ */
537
l = BM_iter_new(&iter, bm, BM_LOOPS_OF_FACE, efa);
538
for (; l; l=BM_iter_step(&iter)) {
539
add_v3_v3(cent, vertexCos[BM_elem_index_get(l->v)]);
544
l = BM_iter_new(&iter, bm, BM_LOOPS_OF_FACE, efa);
545
for (; l; l=BM_iter_step(&iter)) {
546
add_v3_v3(cent, l->v->co);
552
mul_v3_fl(cent, 1.0f/(float)tot);
555
static void emDM_foreachMappedFaceCenter(
557
void (*func)(void *userData, int index, const float co[3], const float no[3]),
560
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
561
float (*polyNos)[3] = NULL;
567
/* ensure for face center calculation */
568
if (bmdm->vertexCos) {
569
BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
570
polyNos = bmdm->polyNos;
572
BLI_assert(polyNos != NULL);
575
efa = BM_iter_new(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
576
for (i=0; efa; efa=BM_iter_step(&iter), i++) {
577
emDM__calcFaceCent(bmdm->tc->bm, efa, cent, bmdm->vertexCos);
578
func(userData, i, cent, polyNos ? polyNos[i] : efa->no);
582
static void emDM_drawMappedFaces(
584
DMSetDrawOptions setDrawOptions,
585
DMSetMaterial setMaterial,
586
DMCompareDrawOptions compareDrawOptions,
590
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
592
struct BMLoop *(*looptris)[3]= bmdm->tc->looptris;
593
const int tottri= bmdm->tc->tottri;
594
const int lasttri= tottri - 1; /* compare agasint this a lot */
595
DMDrawOption draw_option;
597
const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
599
/* GL_ZERO is used to detect if drawing has started or not */
600
GLenum poly_prev= GL_ZERO;
601
GLenum shade_prev= GL_ZERO;
603
(void)setMaterial; /* UNUSED */
605
/* currently unused -- each original face is handled separately */
606
(void)compareDrawOptions;
608
if (bmdm->vertexCos) {
609
/* add direct access */
610
float (*vertexCos)[3]= bmdm->vertexCos;
611
float (*vertexNos)[3]= bmdm->vertexNos;
612
float (*polyNos)[3]= bmdm->polyNos;
613
// int *triPolyMap= bmdm->triPolyMap;
615
BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT | BM_FACE);
617
for (i=0; i < tottri; i++) {
618
BMLoop **l = looptris[i];
622
drawSmooth= (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
624
draw_option = (!setDrawOptions ?
625
DM_DRAW_OPTION_NORMAL :
626
setDrawOptions(userData, BM_elem_index_get(efa)));
627
if (draw_option != DM_DRAW_OPTION_SKIP) {
628
const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
629
if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
631
if (poly_prev != GL_ZERO) glEnd();
632
poly_prev= GL_ZERO; /* force glBegin */
634
glEnable(GL_POLYGON_STIPPLE);
635
glPolygonStipple(stipple_quarttone);
639
if (poly_type != poly_prev) {
640
if (poly_prev != GL_ZERO) glEnd();
641
glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
643
glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
644
glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
645
glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
648
const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
649
if (shade_type != shade_prev) {
650
if (poly_prev != GL_ZERO) glEnd();
651
glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
652
glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
654
if (poly_type != poly_prev) {
655
if (poly_prev != GL_ZERO) glEnd();
656
glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
660
glNormal3fv(polyNos[BM_elem_index_get(efa)]);
661
glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
662
glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
663
glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
666
glNormal3fv(vertexNos[BM_elem_index_get(l[0]->v)]);
667
glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
668
glNormal3fv(vertexNos[BM_elem_index_get(l[1]->v)]);
669
glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
670
glNormal3fv(vertexNos[BM_elem_index_get(l[2]->v)]);
671
glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
675
flush= (draw_option == DM_DRAW_OPTION_STIPPLE);
676
if (!skip_normals && !flush && (i != lasttri))
677
flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
681
poly_prev= GL_ZERO; /* force glBegin */
683
glDisable(GL_POLYGON_STIPPLE);
689
BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_FACE);
691
for (i=0; i < tottri; i++) {
692
BMLoop **l = looptris[i];
696
drawSmooth= (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
698
draw_option = (!setDrawOptions ?
699
DM_DRAW_OPTION_NORMAL :
700
setDrawOptions(userData, BM_elem_index_get(efa)));
701
if (draw_option != DM_DRAW_OPTION_SKIP) {
702
const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
703
if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
705
if (poly_prev != GL_ZERO) glEnd();
706
poly_prev= GL_ZERO; /* force glBegin */
708
glEnable(GL_POLYGON_STIPPLE);
709
glPolygonStipple(stipple_quarttone);
713
if (poly_type != poly_prev) {
714
if (poly_prev != GL_ZERO) glEnd();
715
glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
717
glVertex3fv(l[0]->v->co);
718
glVertex3fv(l[1]->v->co);
719
glVertex3fv(l[2]->v->co);
722
const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
723
if (shade_type != shade_prev) {
724
if (poly_prev != GL_ZERO) glEnd();
725
glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
726
glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
728
if (poly_type != poly_prev) {
729
if (poly_prev != GL_ZERO) glEnd();
730
glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
734
glNormal3fv(efa->no);
735
glVertex3fv(l[0]->v->co);
736
glVertex3fv(l[1]->v->co);
737
glVertex3fv(l[2]->v->co);
740
glNormal3fv(l[0]->v->no);
741
glVertex3fv(l[0]->v->co);
742
glNormal3fv(l[1]->v->no);
743
glVertex3fv(l[1]->v->co);
744
glNormal3fv(l[2]->v->no);
745
glVertex3fv(l[2]->v->co);
749
flush= (draw_option == DM_DRAW_OPTION_STIPPLE);
750
if (!skip_normals && !flush && (i != lasttri)) {
751
flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
756
poly_prev= GL_ZERO; /* force glBegin */
758
glDisable(GL_POLYGON_STIPPLE);
764
/* if non zero we know a face was rendered */
765
if (poly_prev != GL_ZERO) glEnd();
768
static void bmdm_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3],
769
int has_uv, int has_col)
772
luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV);
773
luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV);
774
luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV);
778
lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL);
779
lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL);
780
lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL);
786
static void emDM_drawFacesTex_common(
788
DMSetDrawOptionsTex drawParams,
789
DMSetDrawOptions drawParamsMapped,
790
DMCompareDrawOptions compareDrawOptions,
793
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
794
BMEditMesh *em = bmdm->tc;
795
BMesh *bm= bmdm->tc->bm;
796
float (*vertexCos)[3]= bmdm->vertexCos;
797
float (*vertexNos)[3]= bmdm->vertexNos;
799
MLoopUV *luv[3], dummyluv = {{0}};
800
MLoopCol *lcol[3] = {NULL}, dummylcol = {0};
801
int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
802
int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
804
(void) compareDrawOptions;
806
luv[0] = luv[1] = luv[2] = &dummyluv;
808
dummylcol.r = dummylcol.g = dummylcol.b = dummylcol.a = 255;
810
/* always use smooth shading even for flat faces, else vertex colors wont interpolate */
811
glShadeModel(GL_SMOOTH);
813
BM_mesh_elem_index_ensure(bm, BM_FACE);
816
BM_mesh_elem_index_ensure(bm, BM_VERT);
818
for (i=0; i<em->tottri; i++) {
819
BMLoop **ls = em->looptris[i];
820
MTexPoly *tp= has_uv ? CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY) : NULL;
821
MTFace mtf = {{{0}}};
822
/*unsigned char *cp= NULL;*/ /*UNUSED*/
823
int drawSmooth= BM_elem_flag_test(ls[0]->f, BM_ELEM_SMOOTH);
824
DMDrawOption draw_option;
829
ME_MTEXFACE_CPY(&mtf, tp);
833
draw_option= drawParams(&mtf, has_vcol, efa->mat_nr);
834
else if (drawParamsMapped)
835
draw_option= drawParamsMapped(userData, BM_elem_index_get(efa));
837
draw_option= DM_DRAW_OPTION_NORMAL;
839
if (draw_option != DM_DRAW_OPTION_SKIP) {
841
glBegin(GL_TRIANGLES);
843
glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
845
bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
847
glTexCoord2fv(luv[0]->uv);
849
glColor3ubv((const GLubyte *)&(lcol[0]->r));
850
glVertex3fv(vertexCos[BM_elem_index_get(ls[0]->v)]);
852
glTexCoord2fv(luv[1]->uv);
854
glColor3ubv((const GLubyte *)&(lcol[1]->r));
855
glVertex3fv(vertexCos[BM_elem_index_get(ls[1]->v)]);
857
glTexCoord2fv(luv[2]->uv);
859
glColor3ubv((const GLubyte *)&(lcol[2]->r));
860
glVertex3fv(vertexCos[BM_elem_index_get(ls[2]->v)]);
863
bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
865
glTexCoord2fv(luv[0]->uv);
867
glColor3ubv((const GLubyte *)&(lcol[0]->r));
868
glNormal3fv(vertexNos[BM_elem_index_get(ls[0]->v)]);
869
glVertex3fv(vertexCos[BM_elem_index_get(ls[0]->v)]);
871
glTexCoord2fv(luv[1]->uv);
873
glColor3ubv((const GLubyte *)&(lcol[1]->r));
874
glNormal3fv(vertexNos[BM_elem_index_get(ls[1]->v)]);
875
glVertex3fv(vertexCos[BM_elem_index_get(ls[1]->v)]);
877
glTexCoord2fv(luv[2]->uv);
879
glColor3ubv((const GLubyte *)&(lcol[2]->r));
880
glNormal3fv(vertexNos[BM_elem_index_get(ls[2]->v)]);
881
glVertex3fv(vertexCos[BM_elem_index_get(ls[2]->v)]);
888
BM_mesh_elem_index_ensure(bm, BM_VERT);
890
for (i=0; i<em->tottri; i++) {
891
BMLoop **ls = em->looptris[i];
892
MTexPoly *tp= has_uv ? CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY) : NULL;
893
MTFace mtf = {{{0}}};
894
/*unsigned char *cp= NULL;*/ /*UNUSED*/
895
int drawSmooth= BM_elem_flag_test(ls[0]->f, BM_ELEM_SMOOTH);
896
DMDrawOption draw_option;
901
ME_MTEXFACE_CPY(&mtf, tp);
905
draw_option= drawParams(&mtf, has_vcol, efa->mat_nr);
906
else if (drawParamsMapped)
907
draw_option= drawParamsMapped(userData, BM_elem_index_get(efa));
909
draw_option= DM_DRAW_OPTION_NORMAL;
911
if (draw_option != DM_DRAW_OPTION_SKIP) {
913
glBegin(GL_TRIANGLES);
915
glNormal3fv(efa->no);
917
bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
920
glTexCoord2fv(luv[0]->uv);
922
glColor3ubv((const GLubyte *)&(lcol[0]->r));
923
glVertex3fv(ls[0]->v->co);
926
glTexCoord2fv(luv[1]->uv);
928
glColor3ubv((const GLubyte *)&(lcol[1]->r));
929
glVertex3fv(ls[1]->v->co);
932
glTexCoord2fv(luv[2]->uv);
934
glColor3ubv((const GLubyte *)&(lcol[2]->r));
935
glVertex3fv(ls[2]->v->co);
938
bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
941
glTexCoord2fv(luv[0]->uv);
943
glColor3ubv((const GLubyte *)&(lcol[0]->r));
944
glNormal3fv(ls[0]->v->no);
945
glVertex3fv(ls[0]->v->co);
948
glTexCoord2fv(luv[1]->uv);
950
glColor3ubv((const GLubyte *)&(lcol[1]->r));
951
glNormal3fv(ls[1]->v->no);
952
glVertex3fv(ls[1]->v->co);
955
glTexCoord2fv(luv[2]->uv);
957
glColor3ubv((const GLubyte *)&(lcol[2]->r));
958
glNormal3fv(ls[2]->v->no);
959
glVertex3fv(ls[2]->v->co);
966
glShadeModel(GL_FLAT);
969
static void emDM_drawFacesTex(
971
DMSetDrawOptionsTex setDrawOptions,
972
DMCompareDrawOptions compareDrawOptions,
975
emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
978
static void emDM_drawMappedFacesTex(
980
DMSetDrawOptions setDrawOptions,
981
DMCompareDrawOptions compareDrawOptions,
984
emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
987
static void emDM_drawMappedFacesGLSL(
989
DMSetMaterial setMaterial,
990
DMSetDrawOptions setDrawOptions,
993
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
994
BMesh *bm= bmdm->tc->bm;
995
BMEditMesh *em = bmdm->tc;
996
float (*vertexCos)[3]= bmdm->vertexCos;
997
float (*vertexNos)[3]= bmdm->vertexNos;
1000
DMVertexAttribs attribs;
1001
GPUVertexAttribs gattribs;
1003
int i, b, matnr, new_matnr, dodraw;
1008
memset(&attribs, 0, sizeof(attribs));
1010
/* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1011
glShadeModel(GL_SMOOTH);
1012
BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
1014
#define PASSATTRIB(loop, eve, vert) { \
1015
if (attribs.totorco) { \
1016
float *orco = attribs.orco.array[BM_elem_index_get(eve)]; \
1017
glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \
1019
for (b = 0; b < attribs.tottface; b++) { \
1020
MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
1021
glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv); \
1023
for (b = 0; b < attribs.totmcol; b++) { \
1024
MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
1026
_col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a; \
1027
glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col); \
1029
if (attribs.tottang) { \
1030
float *tang = attribs.tang.array[i*4 + vert]; \
1031
glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \
1036
for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
1040
drawSmooth= BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
1042
if (setDrawOptions && (setDrawOptions(userData, BM_elem_index_get(efa)) == DM_DRAW_OPTION_SKIP))
1045
new_matnr = efa->mat_nr + 1;
1046
if (new_matnr != matnr) {
1047
dodraw = setMaterial(matnr = new_matnr, &gattribs);
1049
DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1053
glBegin(GL_TRIANGLES);
1055
if (vertexCos) glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
1056
else glNormal3fv(efa->no);
1058
PASSATTRIB(ltri[0], ltri[0]->v, 0);
1059
if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1060
else glVertex3fv(ltri[0]->v->co);
1062
PASSATTRIB(ltri[1], ltri[1]->v, 1);
1063
if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1064
else glVertex3fv(ltri[1]->v->co);
1066
PASSATTRIB(ltri[2], ltri[2]->v, 2);
1067
if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1068
else glVertex3fv(ltri[2]->v->co);
1071
PASSATTRIB(ltri[0], ltri[0]->v, 0);
1073
glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
1074
glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1077
glNormal3fv(ltri[0]->v->no);
1078
glVertex3fv(ltri[0]->v->co);
1081
PASSATTRIB(ltri[1], ltri[1]->v, 1);
1083
glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
1084
glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1087
glNormal3fv(ltri[1]->v->no);
1088
glVertex3fv(ltri[1]->v->co);
1091
PASSATTRIB(ltri[2], ltri[2]->v, 2);
1093
glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
1094
glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1097
glNormal3fv(ltri[2]->v->no);
1098
glVertex3fv(ltri[2]->v->co);
1107
static void emDM_drawFacesGLSL(
1109
int (*setMaterial)(int, void *attribs))
1111
dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1114
static void emDM_drawMappedFacesMat(
1116
void (*setMaterial)(void *userData, int, void *attribs),
1117
int (*setFace)(void *userData, int index), void *userData)
1119
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1120
BMesh *bm= bmdm->tc->bm;
1121
BMEditMesh *em = bmdm->tc;
1122
float (*vertexCos)[3]= bmdm->vertexCos;
1123
float (*vertexNos)[3]= bmdm->vertexNos;
1126
DMVertexAttribs attribs= {{{0}}};
1127
GPUVertexAttribs gattribs;
1128
int i, b, matnr, new_matnr;
1132
/* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1133
glShadeModel(GL_SMOOTH);
1135
BM_mesh_elem_index_ensure(bm, BM_VERT|BM_FACE);
1137
#define PASSATTRIB(loop, eve, vert) { \
1138
if (attribs.totorco) { \
1139
float *orco = attribs.orco.array[BM_elem_index_get(eve)]; \
1140
if (attribs.orco.glTexco) \
1141
glTexCoord3fv(orco); \
1143
glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \
1145
for (b = 0; b < attribs.tottface; b++) { \
1146
MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
1147
if (attribs.tface[b].glTexco) \
1148
glTexCoord2fv(_luv->uv); \
1150
glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv); \
1152
for (b = 0; b < attribs.totmcol; b++) { \
1153
MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
1155
_col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a; \
1156
glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col); \
1158
if (attribs.tottang) { \
1159
float *tang = attribs.tang.array[i*4 + vert]; \
1160
glVertexAttrib4fvARB(attribs.tang.glIndex, tang); \
1164
for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
1168
drawSmooth = BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
1171
if (setFace && !setFace(userData, BM_elem_index_get(efa)))
1175
new_matnr = efa->mat_nr + 1;
1176
if (new_matnr != matnr) {
1177
setMaterial(userData, matnr = new_matnr, &gattribs);
1178
DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1182
glBegin(GL_TRIANGLES);
1184
if (vertexCos) glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
1185
else glNormal3fv(efa->no);
1187
PASSATTRIB(ltri[0], ltri[0]->v, 0);
1188
if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1189
else glVertex3fv(ltri[0]->v->co);
1191
PASSATTRIB(ltri[1], ltri[1]->v, 1);
1192
if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1193
else glVertex3fv(ltri[1]->v->co);
1195
PASSATTRIB(ltri[2], ltri[2]->v, 2);
1196
if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1197
else glVertex3fv(ltri[2]->v->co);
1201
PASSATTRIB(ltri[0], ltri[0]->v, 0);
1203
glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
1204
glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1207
glNormal3fv(ltri[0]->v->no);
1208
glVertex3fv(ltri[0]->v->co);
1211
PASSATTRIB(ltri[1], ltri[1]->v, 1);
1213
glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
1214
glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1217
glNormal3fv(ltri[1]->v->no);
1218
glVertex3fv(ltri[1]->v->co);
1221
PASSATTRIB(ltri[2], ltri[2]->v, 2);
1223
glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
1224
glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1227
glNormal3fv(ltri[2]->v->no);
1228
glVertex3fv(ltri[2]->v->co);
1236
static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
1238
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1243
if (bmdm->tc->bm->totvert) {
1244
eve = BM_iter_new(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
1245
for (i=0; eve; eve=BM_iter_step(&iter), i++) {
1246
if (bmdm->vertexCos) {
1247
DO_MINMAX(bmdm->vertexCos[i], min_r, max_r);
1250
DO_MINMAX(eve->co, min_r, max_r);
1259
static int emDM_getNumVerts(DerivedMesh *dm)
1261
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1263
return bmdm->tc->bm->totvert;
1266
static int emDM_getNumEdges(DerivedMesh *dm)
1268
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1270
return bmdm->tc->bm->totedge;
1273
static int emDM_getNumTessFaces(DerivedMesh *dm)
1275
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1277
return bmdm->tc->tottri;
1280
static int emDM_getNumLoops(DerivedMesh *dm)
1282
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1284
return bmdm->tc->bm->totloop;
1287
static int emDM_getNumPolys(DerivedMesh *dm)
1289
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1291
return bmdm->tc->bm->totface;
1294
static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r)
1296
copy_v3_v3(vert_r->co, ev->co);
1298
normal_float_to_short_v3(vert_r->no, ev->no);
1300
vert_r->flag = BM_vert_flag_to_mflag(ev);
1302
if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1303
vert_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
1309
static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
1311
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1314
if (index < 0 || index >= bmdm->tv) {
1315
printf("error in emDM_getVert.\n");
1319
// ev = EDBM_vert_at_index(bmdm->tc, index);
1320
ev = BM_vert_at_index(bmdm->tc->bm, index); /* warning, does list loop, _not_ ideal */
1322
bmvert_to_mvert(bmdm->tc->bm, ev, vert_r);
1323
if (bmdm->vertexCos)
1324
copy_v3_v3(vert_r->co, bmdm->vertexCos[index]);
1327
static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
1329
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1330
BMesh *bm = bmdm->tc->bm;
1333
if (index < 0 || index >= bmdm->te) {
1334
printf("error in emDM_getEdge.\n");
1338
// e = EDBM_edge_at_index(bmdm->tc, index);
1339
e = BM_edge_at_index(bmdm->tc->bm, index); /* warning, does list loop, _not_ ideal */
1341
if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
1342
edge_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT)*255.0f);
1345
if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
1346
edge_r->crease = (unsigned char) (BM_elem_float_data_get(&bm->edata, e, CD_CREASE)*255.0f);
1349
edge_r->flag = BM_edge_flag_to_mflag(e);
1351
edge_r->v1 = BM_elem_index_get(e->v1);
1352
edge_r->v2 = BM_elem_index_get(e->v2);
1355
static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
1357
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1361
if (index < 0 || index >= bmdm->tf) {
1362
printf("error in emDM_getTessFace.\n");
1366
l = bmdm->tc->looptris[index];
1370
face_r->mat_nr = (unsigned char) ef->mat_nr;
1371
face_r->flag = BM_face_flag_to_mflag(ef);
1373
face_r->v1 = BM_elem_index_get(l[0]->v);
1374
face_r->v2 = BM_elem_index_get(l[1]->v);
1375
face_r->v3 = BM_elem_index_get(l[2]->v);
1378
test_index_face(face_r, NULL, 0, 3);
1381
static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
1383
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1384
BMesh *bm = bmdm->tc->bm;
1389
ev = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL);
1390
for (i = 0 ; ev; ev = BM_iter_step(&iter), ++vert_r, ++i) {
1391
if (bmdm->vertexCos)
1392
copy_v3_v3(vert_r->co, bmdm->vertexCos[i]);
1394
copy_v3_v3(vert_r->co, ev->co);
1396
normal_float_to_short_v3(vert_r->no, ev->no);
1398
vert_r->flag = BM_vert_flag_to_mflag(ev);
1400
if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1401
vert_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
1406
static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
1408
BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1411
int has_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT);
1412
int has_crease = CustomData_has_layer(&bm->edata, CD_CREASE);
1414
BM_mesh_elem_index_ensure(bm, BM_VERT);
1416
ee = BM_iter_new(&iter, bm, BM_EDGES_OF_MESH, NULL);
1417
for ( ; ee; ee=BM_iter_step(&iter), edge_r++) {
1419
edge_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->edata, ee, CD_BWEIGHT)*255.0f);
1423
edge_r->crease = (unsigned char) (BM_elem_float_data_get(&bm->edata, ee, CD_CREASE)*255.0f);
1426
edge_r->flag = BM_edge_flag_to_mflag(ee);
1428
edge_r->v1 = BM_elem_index_get(ee->v1);
1429
edge_r->v2 = BM_elem_index_get(ee->v2);
1433
static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *face_r)
1435
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1436
BMesh *bm = bmdm->tc->bm;
1441
BM_mesh_elem_index_ensure(bm, BM_VERT);
1443
for (i=0; i<bmdm->tc->tottri; i++, face_r++) {
1444
l = bmdm->tc->looptris[i];
1447
face_r->mat_nr = (unsigned char) ef->mat_nr;
1449
face_r->flag = BM_face_flag_to_mflag(ef);
1451
face_r->v1 = BM_elem_index_get(l[0]->v);
1452
face_r->v2 = BM_elem_index_get(l[1]->v);
1453
face_r->v3 = BM_elem_index_get(l[2]->v);
1456
test_index_face(face_r, NULL, 0, 3);
1461
static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r)
1463
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1464
BMesh *bm = bmdm->tc->bm;
1469
BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE);
1471
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
1472
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
1473
loop_r->v = BM_elem_index_get(l->v);
1474
loop_r->e = BM_elem_index_get(l->e);
1480
static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r)
1482
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1483
BMesh *bm = bmdm->tc->bm;
1489
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
1490
poly_r->flag = BM_face_flag_to_mflag(f);
1491
poly_r->loopstart = i;
1492
poly_r->totloop = f->len;
1493
poly_r->mat_nr = f->mat_nr;
1500
static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
1502
EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1503
BMesh *bm= bmdm->tc->bm;
1506
datalayer = DM_get_tessface_data_layer(dm, type);
1510
/* layers are store per face for editmesh, we convert to a temporary
1511
* data layer array in the derivedmesh when these are requested */
1512
if (type == CD_MTFACE || type == CD_MCOL) {
1513
const int type_from = (type == CD_MTFACE) ? CD_MTEXPOLY : CD_MLOOPCOL;
1515
char *data, *bmdata;
1516
index = CustomData_get_layer_index(&bm->pdata, type_from);
1519
/* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
1520
const int size = CustomData_sizeof(type);
1523
DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
1524
index = CustomData_get_layer_index(&dm->faceData, type);
1525
dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1527
data = datalayer = DM_get_tessface_data_layer(dm, type);
1529
if (type == CD_MTFACE) {
1530
for (i = 0; i < bmdm->tc->tottri; i++, data += size) {
1531
BMFace *efa = bmdm->tc->looptris[i][0]->f;
1532
bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
1533
ME_MTEXFACE_CPY(((MTFace *)data), ((MTexPoly *)bmdata));
1534
for (j = 0; j < 3; j++) {
1535
bmdata = CustomData_bmesh_get(&bm->ldata, bmdm->tc->looptris[i][j]->head.data, CD_MLOOPUV);
1536
copy_v2_v2(((MTFace *)data)->uv[j], ((MLoopUV *)bmdata)->uv);
1541
for (i = 0; i < bmdm->tc->tottri; i++, data += size) {
1542
for (j = 0; j < 3; j++) {
1543
bmdata = CustomData_bmesh_get(&bm->ldata, bmdm->tc->looptris[i][j]->head.data, CD_MLOOPCOL);
1544
MESH_MLOOPCOL_TO_MCOL(((MLoopCol *)bmdata), (((MCol *)data) + j));
1554
static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
1556
EditDerivedBMesh *emdm= (EditDerivedBMesh*) dm;
1562
BM_ITER_MESH (eve, &iter, emdm->tc->bm, BM_VERTS_OF_MESH) {
1563
if (emdm->vertexCos) {
1564
copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
1567
copy_v3_v3(cos_r[i], eve->co);
1574
static void emDM_release(DerivedMesh *dm)
1576
EditDerivedBMesh *bmdm= (EditDerivedBMesh *)dm;
1578
if (DM_release(dm)) {
1579
if (bmdm->vertexCos) {
1580
MEM_freeN(bmdm->vertexCos);
1581
MEM_freeN(bmdm->vertexNos);
1582
MEM_freeN(bmdm->polyNos);
1589
static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
1591
EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1593
return &bmdm->tc->bm->vdata;
1596
static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
1598
EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1600
return &bmdm->tc->bm->edata;
1603
static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
1605
EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1607
return &bmdm->dm.faceData;
1610
static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
1612
EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1614
return &bmdm->tc->bm->ldata;
1617
static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
1619
EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1621
return &bmdm->tc->bm->pdata;
1625
DerivedMesh *getEditDerivedBMesh(
1628
float (*vertexCos)[3])
1630
EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
1635
DM_init((DerivedMesh*)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert,
1636
em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface);
1638
bmdm->dm.getVertCos = emDM_getVertCos;
1639
bmdm->dm.getMinMax = emDM_getMinMax;
1641
bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
1642
bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
1643
bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
1644
bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
1645
bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout;
1647
bmdm->dm.getNumVerts = emDM_getNumVerts;
1648
bmdm->dm.getNumEdges = emDM_getNumEdges;
1649
bmdm->dm.getNumTessFaces = emDM_getNumTessFaces;
1650
bmdm->dm.getNumLoops = emDM_getNumLoops;
1651
bmdm->dm.getNumPolys = emDM_getNumPolys;
1653
bmdm->dm.getVert = emDM_getVert;
1654
bmdm->dm.getEdge = emDM_getEdge;
1655
bmdm->dm.getTessFace = emDM_getTessFace;
1656
bmdm->dm.copyVertArray = emDM_copyVertArray;
1657
bmdm->dm.copyEdgeArray = emDM_copyEdgeArray;
1658
bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray;
1659
bmdm->dm.copyLoopArray = emDM_copyLoopArray;
1660
bmdm->dm.copyPolyArray = emDM_copyPolyArray;
1662
bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
1664
bmdm->dm.calcNormals = emDM_calcNormals;
1665
bmdm->dm.recalcTessellation = emDM_recalcTessellation;
1667
bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
1668
bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
1669
bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
1671
bmdm->dm.drawEdges = emDM_drawEdges;
1672
bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
1673
bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
1674
bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
1675
bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
1676
bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
1677
bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
1678
bmdm->dm.drawFacesTex = emDM_drawFacesTex;
1679
bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
1680
bmdm->dm.drawUVEdges = emDM_drawUVEdges;
1682
bmdm->dm.release = emDM_release;
1684
bmdm->vertexCos = vertexCos;
1686
if (CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) {
1691
DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
1693
eve = BM_iter_new(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
1694
for (i=0; eve; eve=BM_iter_step(&iter), i++)
1695
DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
1696
CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
1706
BM_mesh_elem_index_ensure(bm, BM_VERT);
1708
bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos) * bm->totvert, "bmdm_vno");
1709
bmdm->polyNos = MEM_mallocN(sizeof(*bmdm->polyNos)*bm->totface, "bmdm_pno");
1712
BM_ITER_MESH (efa, &fiter, bm, BM_FACES_OF_MESH) {
1713
BM_elem_index_set(efa, i); /* set_inline */
1714
BM_face_normal_update_vcos(bm, efa, bmdm->polyNos[i], (float const (*)[3])vertexCos);
1717
bm->elem_index_dirty &= ~BM_FACE;
1719
eve=BM_iter_new(&viter, bm, BM_VERTS_OF_MESH, NULL);
1720
for (i=0; eve; eve=BM_iter_step(&viter), i++) {
1721
float *no = bmdm->vertexNos[i];
1722
BM_ITER_ELEM (efa, &fiter, eve, BM_FACES_OF_VERT) {
1723
add_v3_v3(no, bmdm->polyNos[BM_elem_index_get(efa)]);
1726
/* following Mesh convention; we use vertex coordinate itself
1727
* for normal in this case */
1728
if (normalize_v3(no)==0.0) {
1729
copy_v3_v3(no, vertexCos[i]);
1735
return (DerivedMesh*) bmdm;
1739
* \brief Return the BMEditMesh for a given object
1741
* \note this function assumes this is a mesh object,
1742
* don't add NULL data check here. caller must do that
1744
BMEditMesh *BMEdit_FromObject(Object *ob)
1746
BLI_assert(ob->type == OB_MESH);
1747
return ((Mesh *)ob->data)->edit_btmesh;