2
* $Id: retopo.c 16914 2008-10-04 11:04:09Z ton $
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
* The Original Code is Copyright (C) 2006 by Nicholas Bishop
21
* All rights reserved.
23
* The Original Code is: all of this file.
25
* Contributor(s): none yet.
27
* ***** END GPL LICENSE BLOCK *****
29
* Implements the Retopo tools
35
#include "MEM_guardedalloc.h"
37
#include "DNA_curve_types.h"
38
#include "DNA_mesh_types.h"
39
#include "DNA_meshdata_types.h"
40
#include "DNA_object_types.h"
41
#include "DNA_scene_types.h"
42
#include "DNA_screen_types.h"
43
#include "DNA_space_types.h"
44
#include "DNA_userdef_types.h"
45
#include "DNA_view3d_types.h"
47
#include "BDR_editobject.h"
49
#include "BIF_editmesh.h"
50
#include "BIF_editmode_undo.h"
52
#include "BIF_glutil.h"
53
#include "BIF_mywindow.h"
54
#include "BIF_retopo.h"
55
#include "BIF_screen.h"
56
#include "BIF_space.h"
57
#include "BIF_toolbox.h"
59
#include "BKE_curve.h"
60
#include "BKE_depsgraph.h"
61
#include "BKE_global.h"
64
#include "BLI_blenlib.h"
65
#include "BLI_editVert.h"
67
#include "BSE_drawview.h"
75
#define _USE_MATH_DEFINES
81
typedef struct RetopoPaintHit {
82
struct RetopoPaintHit *next, *prev;
83
RetopoPaintPoint *intersection;
88
static void retopo_do_2d(View3D *v3d, double proj[2], float *v, char adj);
91
static void retopo_paint_debug_print(RetopoPaintData *rpd)
96
for(l= rpd->lines.first; l; l= l->next) {
98
for(p= l->points.first; p; p= p->next) {
99
printf(" Point(%d: %d,%d)\n",p->index,p->loc.x,p->loc.y);
108
RetopoPaintData *get_retopo_paint_data(void)
110
if(!retopo_mesh_paint_check()) return NULL;
111
if(!G.editMesh) return NULL;
112
return G.editMesh->retopo_paint_data;
115
char retopo_mesh_paint_check(void)
117
return retopo_mesh_check() && G.scene->toolsettings->retopo_mode & RETOPO_PAINT;
120
void retopo_free_paint_data(RetopoPaintData *rpd)
124
for(l= rpd->lines.first; l; l= l->next) {
125
BLI_freelistN(&l->points);
126
BLI_freelistN(&l->hitlist);
128
BLI_freelistN(&rpd->lines);
130
BLI_freelistN(&rpd->intersections);
136
void retopo_free_paint(void)
138
retopo_free_paint_data(G.editMesh->retopo_paint_data);
139
G.editMesh->retopo_paint_data= NULL;
142
char line_intersection_2d(const vec2s *a, const vec2s *b, const vec2s *c, const vec2s *d, vec2s *out,
146
*r= (a->y - c->y) * (d->x - c->x) - (a->x - c->x) * (d->y - c->y);
147
*s= (a->y - c->y) * (b->x - a->x) - (a->x - c->x) * (b->y - a->y);
148
den= (b->x - a->x) * (d->y - c->y) - (b->y - a->y) * (d->x - c->x);
150
if((a->x==b->x && a->y==b->y) || (c->x==d->x && c->y==d->y)) return 0;
157
if(*s<0 || *s>=1 || *r<0 || *r>=1) return 0;
159
out->x= a->x + *r*(b->x - a->x);
160
out->y= a->y + *r*(b->y - a->y);
164
void retopo_paint_add_line_hit(RetopoPaintLine *l, RetopoPaintPoint *p, RetopoPaintPoint *intersection, float w)
166
RetopoPaintHit *prev, *hit= MEM_callocN(sizeof(RetopoPaintHit),"RetopoPaintHit");
168
hit->intersection= intersection;
169
hit->index= p->index;
172
prev= l->hitlist.first;
174
BLI_addtail(&l->hitlist,hit);
176
else if(prev->index>hit->index) {
177
BLI_addhead(&l->hitlist,hit);
180
/* Move forward until we hit the next highest index */
182
if(prev->next->index > hit->index) break;
185
/* Move backward until we hit the next lowest where */
186
while(prev->prev && prev->prev->index==prev->index &&
187
prev->where > hit->where)
189
BLI_insertlink(&l->hitlist,prev,hit);
192
/* Removed duplicate intersections */
193
if(hit->prev && hit->prev->intersection==hit->intersection) {
194
BLI_freelinkN(&l->hitlist,hit);
198
char retopo_paint_add_intersection(RetopoPaintData *rpd, RetopoPaintLine *l1, RetopoPaintPoint *p1,
199
RetopoPaintLine *l2, RetopoPaintPoint *p2, vec2s *out, float r, float s)
201
RetopoPaintPoint *p, *hit;
204
for(p=rpd->intersections.first; p; p= p->next) {
205
if(sqrt(pow(p->loc.x-out->x,2)+pow(p->loc.y-out->y,2))<7) {
212
hit= MEM_callocN(sizeof(RetopoPaintPoint),"Retopo paint intersection");
215
BLI_addtail(&rpd->intersections,hit);
220
retopo_paint_add_line_hit(l1,p1,hit,r);
221
retopo_paint_add_line_hit(l2,p2,hit,s);
227
/* Returns 1 if a new intersection was added */
228
char do_line_intersection(RetopoPaintData *rpd, RetopoPaintLine *l1, RetopoPaintPoint *p1,
229
RetopoPaintLine *l2, RetopoPaintPoint *p2)
233
if(line_intersection_2d(&p1->loc, &p1->next->loc,
234
&p2->loc, &p2->next->loc,
236
if(retopo_paint_add_intersection(rpd,l1,p1,l2,p2,&out,r,s))
242
typedef struct FaceNode {
243
struct FaceNode *next, *prev;
247
char faces_equal(EditFace *f1, EditFace *f2)
249
return editface_containsVert(f2,f1->v1) &&
250
editface_containsVert(f2,f1->v2) &&
251
editface_containsVert(f2,f1->v3) &&
252
(f1->v4 ? editface_containsVert(f2,f1->v4) : 1);
255
EditFace *addfaceif(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4)
259
for(efa= em->faces.first; efa; efa= efa->next) {
260
if(editface_containsVert(efa,v1) &&
261
editface_containsVert(efa,v2) &&
262
editface_containsVert(efa,v3) &&
263
(v4 ? editface_containsVert(efa,v4) : 1))
267
return addfacelist(v1,v2,v3,v4,NULL,NULL);
270
void retopo_paint_apply(void)
272
RetopoPaintData *rpd= G.editMesh->retopo_paint_data;
276
RetopoPaintLine *l1, *l2;
277
RetopoPaintPoint *p1, *p2;
278
unsigned hitcount= 0;
283
/* Find intersections */
284
BLI_freelistN(&rpd->intersections);
285
for(l1= rpd->lines.first; l1; l1= l1->next) {
286
for(l2= rpd->lines.first; l2; l2= l2->next) {
288
for(p1= l1->points.first; p1 && p1!=l1->points.last; p1= p1->next) {
289
for(p2= l2->points.first; p2 && p2!=l2->points.last; p2= p2->next) {
291
if(do_line_intersection(rpd,l1,p1,l2,p2))
301
l1= rpd->lines.first;
302
for(hit= l1->hitlist.first; hit; hit= hit->next) {
303
printf("\nhit(%p,%d) ",hit->intersection,hit->index);
308
for(eve= G.editMesh->verts.first; eve; eve= eve->next)
312
for(i=0; i<hitcount; ++i) {
313
RetopoPaintPoint *intersection= BLI_findlink(&rpd->intersections,i);
314
double proj[2] = {intersection->loc.x, intersection->loc.y};
315
retopo_do_2d(rpd->paint_v3d, proj, hitco, 1);
316
intersection->eve= addvertlist(hitco, NULL);
317
intersection->eve->f= SELECT;
320
for(l1= rpd->lines.first; l1; l1= l1->next) {
321
unsigned etcount= BLI_countlist(&l1->hitlist);
323
for(h= l1->hitlist.first; (h && h->next); h= h->next)
324
addedgelist(h->intersection->eve,h->next->intersection->eve,NULL);
325
if(etcount>=3 && l1->cyclic)
326
addedgelist(((RetopoPaintHit*)l1->hitlist.first)->intersection->eve,
327
((RetopoPaintHit*)l1->hitlist.last)->intersection->eve, NULL);
331
addfaces_from_edgenet();
337
void add_rppoint(RetopoPaintLine *l, short x, short y)
339
RetopoPaintPoint *p= MEM_callocN(sizeof(RetopoPaintPoint),"RetopoPaintPoint");
343
BLI_addtail(&l->points,p);
344
p->index= p->prev?p->prev->index+1:0;
349
retopo_do_2d(G.editMesh->retopo_paint_data->paint_v3d, proj, p->co, 1);
351
RetopoPaintLine *add_rpline(RetopoPaintData *rpd)
353
RetopoPaintLine *l= MEM_callocN(sizeof(RetopoPaintLine),"RetopoPaintLine");
354
BLI_addtail(&rpd->lines,l);
358
void retopo_paint_toggle_cyclic(RetopoPaintLine *l)
363
RetopoPaintPoint *pf= l->points.first;
366
add_rppoint(l, pf->loc.x, pf->loc.y);
367
l->cyclic= l->points.last;
370
BLI_freelinkN(&l->points,l->cyclic);
375
void retopo_paint_add_line(RetopoPaintData *rpd, short mouse[2])
377
RetopoPaintLine *l= add_rpline(rpd);
378
float range[2]= {mouse[0]-rpd->sloc[0],mouse[1]-rpd->sloc[1]};
381
/* Add initial point */
382
add_rppoint(l,rpd->sloc[0],rpd->sloc[1]);
383
for(i=0; i<G.scene->toolsettings->line_div; ++i) {
384
const float mul= (i+1.0f) / G.scene->toolsettings->line_div;
385
add_rppoint(l,rpd->sloc[0] + range[0]*mul,rpd->sloc[1] + range[1]*mul);
388
allqueue(REDRAWVIEW3D,0);
391
void retopo_paint_add_ellipse(RetopoPaintData *rpd, short mouse[2])
396
for (i=0; i<G.scene->toolsettings->ellipse_div; i++) {
397
float t= (float) i / G.scene->toolsettings->ellipse_div;
398
float cur= t*(M_PI*2);
400
float w= abs(mouse[0]-rpd->sloc[0]);
401
float h= abs(mouse[1]-rpd->sloc[1]);
403
add_rppoint(rpd->lines.last,cos(cur)*w+rpd->sloc[0],sin(cur)*h+rpd->sloc[1]);
406
retopo_paint_toggle_cyclic(rpd->lines.last);
408
allqueue(REDRAWVIEW3D,0);
411
void retopo_end_okee(void)
413
if(okee("Apply retopo paint?"))
414
retopo_paint_apply();
417
G.scene->toolsettings->retopo_mode &= ~RETOPO_PAINT;
420
void retopo_paint_toggle(void *a, void *b)
422
/* Note that these operations are reversed because mode bit has already been set! */
423
if(retopo_mesh_paint_check()) { /* Activate retopo paint */
424
RetopoPaintData *rpd= MEM_callocN(sizeof(RetopoPaintData),"RetopoPaintData");
426
G.editMesh->retopo_paint_data= rpd;
427
G.scene->toolsettings->retopo_paint_tool= RETOPO_PEN;
429
rpd->nearest.line= NULL;
430
G.scene->toolsettings->line_div= 25;
431
G.scene->toolsettings->ellipse_div= 25;
432
G.scene->toolsettings->retopo_hotspot= 1;
433
} else retopo_end_okee();
435
BIF_undo_push("Retopo toggle");
437
allqueue(REDRAWVIEW3D, 1);
440
void retopo_paint_view_update(struct View3D *v3d)
442
RetopoPaintData *rpd= get_retopo_paint_data();
444
if(rpd && rpd->paint_v3d==v3d) {
449
for(l= rpd->lines.first; l; l= l->next) {
450
for(p= l->points.first; p; p= p->next) {
451
gluProject(p->co[0],p->co[1],p->co[2], v3d->retopo_view_data->mats.modelview,
452
v3d->retopo_view_data->mats.projection,
453
(GLint *)v3d->retopo_view_data->mats.viewport, &ux, &uy, &uz);
461
void retopo_force_update(void)
463
RetopoPaintData *rpd= get_retopo_paint_data();
466
View3D *vd= rpd->paint_v3d;
469
if(vd->depths) vd->depths->damaged= 1;
470
retopo_queue_updates(vd);
471
if(retopo_mesh_paint_check() && vd->retopo_view_data)
472
allqueue(REDRAWVIEW3D, 0);
477
/* Returns 1 if event should be processed by caller, 0 otherwise */
478
char retopo_paint(const unsigned short event)
480
RetopoPaintData *rpd= get_retopo_paint_data();
486
char lbut= get_mbut() & (U.flag & USER_LMOUSESELECT ? R_MOUSE : L_MOUSE);
488
if(rpd->paint_v3d && rpd->paint_v3d!=G.vd) return 1;
490
getmouseco_areawin(mouse);
492
if(rpd->in_drag && !lbut) { /* End drag */
495
switch(G.scene->toolsettings->retopo_paint_tool) {
499
retopo_paint_add_line(rpd, mouse);
502
retopo_paint_add_ellipse(rpd, mouse);
505
BIF_undo_push("Retopo paint");
511
switch(G.scene->toolsettings->retopo_paint_tool) {
513
if(rpd->in_drag && rpd->lines.last) {
516
if(((RetopoPaintPoint*)l->points.last)->loc.x != mouse[0] ||
517
((RetopoPaintPoint*)l->points.last)->loc.y != mouse[1]) {
518
add_rppoint(l,mouse[0],mouse[1]);
520
rpd->nearest.line= NULL;
523
} else if(G.scene->toolsettings->retopo_hotspot) { /* Find nearest endpoint */
525
RetopoPaintLine *l= rpd->lines.first;
526
RetopoPaintSel n= {NULL,NULL,l,1};
527
sdist= rpd->seldist + 10;
528
for(l= rpd->lines.first; l; l= l->next) {
530
RetopoPaintPoint *p1= l->points.first, *p2= l->points.last;
532
tdist= sqrt(pow(mouse[0] - p1->loc.x,2)+pow(mouse[1] - p1->loc.y,2));
533
if(tdist < sdist && tdist < rpd->seldist) {
538
tdist= sqrt(pow(mouse[0] - p2->loc.x,2)+pow(mouse[1] - p2->loc.y,2));
539
if(tdist < sdist && tdist < rpd->seldist) {
547
if(sdist < rpd->seldist)
549
else rpd->nearest.line= NULL;
557
allqueue(REDRAWVIEW3D,0);
561
retopo_paint_apply();
563
G.scene->toolsettings->retopo_mode&= ~RETOPO_PAINT;
566
BIF_undo_push("Retopo toggle");
568
allqueue(REDRAWVIEW3D, 1);
569
allqueue(REDRAWBUTSEDIT, 0);
572
retopo_paint_toggle_cyclic(rpd->lines.last);
573
BIF_undo_push("Retopo toggle cyclic");
574
allqueue(REDRAWVIEW3D, 0);
577
G.scene->toolsettings->retopo_paint_tool= RETOPO_ELLIPSE;
578
allqueue(REDRAWVIEW3D, 1);
581
G.scene->toolsettings->retopo_hotspot= !G.scene->toolsettings->retopo_hotspot;
582
allqueue(REDRAWVIEW3D, 1);
585
G.scene->toolsettings->retopo_paint_tool= RETOPO_LINE;
586
allqueue(REDRAWVIEW3D, 1);
589
G.scene->toolsettings->retopo_paint_tool= RETOPO_PEN;
590
allqueue(REDRAWVIEW3D, 1);
596
BLI_freelistN(&l->points);
597
BLI_freelistN(&l->hitlist);
598
BLI_freelinkN(&rpd->lines, l);
599
if(rpd->nearest.line == l)
600
rpd->nearest.line= NULL;
601
BIF_undo_push("Erase line");
602
allqueue(REDRAWVIEW3D, 0);
606
if(!rpd->in_drag) { /* Start new drag */
610
rpd->paint_v3d= G.vd;
612
/* Location of mouse down */
613
rpd->sloc[0]= mouse[0];
614
rpd->sloc[1]= mouse[1];
616
switch(G.scene->toolsettings->retopo_paint_tool) {
618
if(rpd->nearest.line) {
619
RetopoPaintPoint *p, *pt;
622
BLI_remlink(&rpd->lines,rpd->nearest.line);
623
BLI_addtail(&rpd->lines,rpd->nearest.line);
625
/* Check if we need to reverse the line */
626
if(rpd->nearest.first) {
627
for(p= rpd->nearest.line->points.first; p; p= p->prev) {
632
pt= rpd->nearest.line->points.first;
633
rpd->nearest.line->points.first= rpd->nearest.line->points.last;
634
rpd->nearest.line->points.last= pt;
636
/* Reverse indices */
638
for(p= rpd->nearest.line->points.first; p; p= p->next)
643
add_rppoint(rpd->lines.last,mouse[0],mouse[1]);
651
allqueue(REDRAWVIEW3D, 0);
657
case PAD0: case PAD1: case PAD2: case PAD3: case PAD4:
658
case PAD5: case PAD6: case PAD7: case PAD8: case PAD9:
659
case PADMINUS: case PADPLUSKEY:
665
void retopo_draw_paint_lines()
667
RetopoPaintData *rpd= get_retopo_paint_data();
669
if(rpd && rpd->paint_v3d==G.vd) {
676
/* Draw existing lines */
677
for(l= rpd->lines.first; l; l= l->next) {
678
if(l==rpd->lines.last)
680
glBegin(l->cyclic?GL_LINE_LOOP:GL_LINE_STRIP);
681
for(p= l->points.first; p; p= p->next) {
682
glVertex2s(p->loc.x,p->loc.y);
688
if(G.scene->toolsettings->retopo_paint_tool==RETOPO_ELLIPSE && rpd->in_drag) {
690
getmouseco_areawin(mouse);
693
fdrawXORellipse(rpd->sloc[0],rpd->sloc[1],abs(mouse[0]-rpd->sloc[0]),abs(mouse[1]-rpd->sloc[1]));
696
else if(G.scene->toolsettings->retopo_paint_tool==RETOPO_LINE && rpd->in_drag) {
698
getmouseco_areawin(mouse);
701
sdrawXORline(rpd->sloc[0],rpd->sloc[1],mouse[0],mouse[1]);
704
else if(rpd->nearest.line) { /* Draw selection */
705
RetopoPaintPoint *p= rpd->nearest.first ? rpd->nearest.line->points.first :
706
rpd->nearest.line->points.last;
708
fdrawXORcirc(p->loc.x, p->loc.y, rpd->seldist);
715
RetopoPaintData *retopo_paint_data_copy(RetopoPaintData *rpd)
717
RetopoPaintData *copy;
718
RetopoPaintLine *l, *lcp;
719
RetopoPaintPoint *p, *pcp;
721
if(!rpd) return NULL;
723
copy= MEM_mallocN(sizeof(RetopoPaintData),"RetopoPaintDataCopy");
725
memcpy(copy,rpd,sizeof(RetopoPaintData));
726
copy->lines.first= copy->lines.last= NULL;
727
copy->nearest.next= copy->nearest.prev= NULL;
728
copy->nearest.line= NULL;
729
copy->nearest.first= 0;
731
for(l= rpd->lines.first; l; l= l->next) {
732
lcp= MEM_dupallocN(l);
733
BLI_addtail(©->lines, lcp);
735
lcp->hitlist.first= lcp->hitlist.last= NULL;
736
lcp->points.first= lcp->points.last= NULL;
739
for(p= l->points.first; p; p= p->next) {
740
pcp= MEM_dupallocN(p);
741
BLI_addtail(&lcp->points, pcp);
746
copy->intersections.first= copy->intersections.last= NULL;
751
char retopo_mesh_check(void)
753
return G.obedit && G.obedit->type==OB_MESH && (G.scene->toolsettings->retopo_mode & RETOPO);
755
char retopo_curve_check(void)
757
return G.obedit && (G.obedit->type==OB_CURVE ||
758
G.obedit->type==OB_SURF) && (((Curve*)G.obedit->data)->flag & CU_RETOPO);
761
void retopo_toggle(void *j1,void *j2)
763
if(retopo_mesh_check() || retopo_curve_check()) {
764
if(G.vd->depths) G.vd->depths->damaged= 1;
765
retopo_queue_updates(G.vd);
767
if(G.editMesh && G.scene->toolsettings->retopo_mode & RETOPO_PAINT)
771
allqueue(REDRAWBUTSEDIT, 0);
772
allqueue(REDRAWVIEW3D, 0);
775
static void retopo_do_2d(View3D *v3d, double proj[2], float *v, char adj)
777
/* Check to make sure vert is visible in window */
778
if(proj[0]>0 && proj[1]>0 && proj[0] < v3d->depths->w && proj[1] < v3d->depths->h) {
779
float depth= v3d->depths->depths[((int)proj[1])*v3d->depths->w+((int)proj[0])];
782
/* Don't modify the point if it'll be mapped to the background */
783
if(depth==v3d->depths->depth_range[1]) {
785
/* Find the depth of (0,0,0); */
786
gluProject(0,0,0,v3d->retopo_view_data->mats.modelview,
787
v3d->retopo_view_data->mats.projection,
788
(GLint *)v3d->retopo_view_data->mats.viewport,&px,&py,&pz);
794
/* Find 3D location with new depth (unproject) */
795
gluUnProject(proj[0],proj[1],depth,v3d->retopo_view_data->mats.modelview,
796
v3d->retopo_view_data->mats.projection,
797
(GLint *)v3d->retopo_view_data->mats.viewport,&px,&py,&pz);
805
void retopo_do_vert(View3D *v3d, float *v)
809
/* Find 2D location (project) */
810
gluProject(v[0],v[1],v[2],v3d->retopo_view_data->mats.modelview,v3d->retopo_view_data->mats.projection,
811
(GLint *)v3d->retopo_view_data->mats.viewport,&proj[0],&proj[1],&proj[2]);
813
retopo_do_2d(v3d,proj,v,0);
816
void retopo_do_all(void)
818
RetopoViewData *rvd= G.vd->retopo_view_data;
819
if(retopo_mesh_check()) {
821
EditMesh *em= G.editMesh;
824
/* Apply retopo to all selected vertices */
825
eve= em->verts.first;
828
retopo_do_vert(G.vd,eve->co);
832
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
833
allqueue(REDRAWVIEW3D, 0);
836
else if(retopo_curve_check()) {
838
extern ListBase editNurb;
843
for(nu= editNurb.first; nu; nu= nu->next)
845
if(nu->type & CU_2D) {
846
/* Can't wrap a 2D curve onto a 3D surface */
848
else if(nu->type & CU_BEZIER) {
849
for(i=0; i<nu->pntsu; ++i) {
850
if(nu->bezt[i].f1 & SELECT)
851
retopo_do_vert(G.vd, nu->bezt[i].vec[0]);
852
if(nu->bezt[i].f2 & SELECT)
853
retopo_do_vert(G.vd, nu->bezt[i].vec[1]);
854
if(nu->bezt[i].f3 & SELECT)
855
retopo_do_vert(G.vd, nu->bezt[i].vec[2]);
860
for(i=0; i<nu->pntsv; ++i) {
861
for(j=0; j<nu->pntsu; ++j, ++bp) {
863
retopo_do_vert(G.vd,bp->vec);
871
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
872
allqueue(REDRAWVIEW3D, 0);
877
void retopo_do_all_cb(void *j1, void *j2)
879
/* This is called from editbuttons, so user needs to specify view */
880
if(!select_area(SPACE_VIEW3D)) return;
882
if(G.vd->drawtype == OB_WIRE) {
883
error("Cannot apply retopo in wireframe mode");
888
BIF_undo_push("Retopo all");
891
void retopo_queue_updates(View3D *v3d)
893
if(retopo_mesh_check() || retopo_curve_check()) {
894
if(!v3d->retopo_view_data)
895
v3d->retopo_view_data= MEM_callocN(sizeof(RetopoViewData),"RetopoViewData");
897
v3d->retopo_view_data->queue_matrix_update= 1;
899
allqueue(REDRAWVIEW3D, 0);
903
void retopo_matrix_update(View3D *v3d)
905
RetopoPaintData *rpd= get_retopo_paint_data();
906
if((retopo_mesh_check() || retopo_curve_check()) && (!rpd || rpd->paint_v3d==v3d)) {
907
RetopoViewData *rvd= v3d->retopo_view_data;
909
rvd= MEM_callocN(sizeof(RetopoViewData),"RetopoViewData");
910
v3d->retopo_view_data= rvd;
911
rvd->queue_matrix_update= 1;
913
if(rvd && rvd->queue_matrix_update) {
914
bgl_get_mats(&rvd->mats);
916
rvd->queue_matrix_update= 0;
921
void retopo_free_view_data(View3D *v3d)
923
if(v3d->retopo_view_data) {
924
MEM_freeN(v3d->retopo_view_data);
925
v3d->retopo_view_data= NULL;