459 lines
9.7 KiB
C
459 lines
9.7 KiB
C
/**
|
|
* $Id$
|
|
*
|
|
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version. The Blender
|
|
* Foundation also sells licenses for use in proprietary software under
|
|
* the Blender License. See http://www.blender.org/BL/ for information
|
|
* about this.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
* All rights reserved.
|
|
*
|
|
* The Original Code is: all of this file.
|
|
*
|
|
* Contributor(s): none yet.
|
|
*
|
|
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "DNA_mesh_types.h"
|
|
#include "DNA_meshdata_types.h"
|
|
#include "DNA_scene_types.h"
|
|
#include "DNA_screen_types.h"
|
|
#include "DNA_space_types.h"
|
|
|
|
#include "BKE_global.h"
|
|
#include "BKE_mesh.h"
|
|
#include "BKE_utildefines.h"
|
|
|
|
#include "BLI_arithb.h"
|
|
#include "BLI_edgehash.h"
|
|
|
|
#include "BIF_editsima.h"
|
|
#include "BIF_space.h"
|
|
#include "BIF_screen.h"
|
|
|
|
#include "blendef.h"
|
|
#include "mydevice.h"
|
|
|
|
#include "BDR_unwrapper.h"
|
|
|
|
#include "PIL_time.h"
|
|
|
|
#include "parametrizer.h"
|
|
|
|
/* Set tface seams based on edge data, uses hash table to find seam edges. */
|
|
|
|
static void hash_add_face(EdgeHash *ehash, MFace *mf)
|
|
{
|
|
BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL);
|
|
BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL);
|
|
if(mf->v4) {
|
|
BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL);
|
|
BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL);
|
|
}
|
|
else
|
|
BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL);
|
|
}
|
|
|
|
void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index)
|
|
{
|
|
MTFace *tf;
|
|
MFace *mf;
|
|
int a, doit=1, mark=0;
|
|
char *linkflag;
|
|
EdgeHash *ehash, *seamhash;
|
|
MEdge *med;
|
|
|
|
ehash= BLI_edgehash_new();
|
|
seamhash = BLI_edgehash_new();
|
|
linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv");
|
|
|
|
for(med=me->medge, a=0; a < me->totedge; a++, med++)
|
|
if(med->flag & ME_SEAM)
|
|
BLI_edgehash_insert(seamhash, med->v1, med->v2, NULL);
|
|
|
|
if (mode==0 || mode==1) {
|
|
/* only put face under cursor in array */
|
|
mf= ((MFace*)me->mface) + index;
|
|
hash_add_face(ehash, mf);
|
|
linkflag[index]= 1;
|
|
}
|
|
else {
|
|
/* fill array by selection */
|
|
tf= me->mtface;
|
|
mf= me->mface;
|
|
for(a=0; a<me->totface; a++, tf++, mf++) {
|
|
if(tf->flag & TF_HIDE);
|
|
else if(tf->flag & TF_SELECT) {
|
|
hash_add_face(ehash, mf);
|
|
linkflag[a]= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
while(doit) {
|
|
doit= 0;
|
|
|
|
/* expand selection */
|
|
tf= me->mtface;
|
|
mf= me->mface;
|
|
for(a=0; a<me->totface; a++, tf++, mf++) {
|
|
if(tf->flag & TF_HIDE)
|
|
continue;
|
|
|
|
if(!linkflag[a]) {
|
|
mark= 0;
|
|
|
|
if(!BLI_edgehash_haskey(seamhash, mf->v1, mf->v2))
|
|
if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2))
|
|
mark= 1;
|
|
if(!BLI_edgehash_haskey(seamhash, mf->v2, mf->v3))
|
|
if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3))
|
|
mark= 1;
|
|
if(mf->v4) {
|
|
if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v4))
|
|
if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4))
|
|
mark= 1;
|
|
if(!BLI_edgehash_haskey(seamhash, mf->v4, mf->v1))
|
|
if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1))
|
|
mark= 1;
|
|
}
|
|
else if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v1))
|
|
if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1))
|
|
mark = 1;
|
|
|
|
if(mark) {
|
|
linkflag[a]= 1;
|
|
hash_add_face(ehash, mf);
|
|
doit= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
BLI_edgehash_free(ehash, NULL);
|
|
BLI_edgehash_free(seamhash, NULL);
|
|
|
|
if(mode==0 || mode==2) {
|
|
for(a=0, tf=me->mtface; a<me->totface; a++, tf++)
|
|
if(linkflag[a])
|
|
tf->flag |= TF_SELECT;
|
|
else
|
|
tf->flag &= ~TF_SELECT;
|
|
}
|
|
else if(mode==1) {
|
|
for(a=0, tf=me->mtface; a<me->totface; a++, tf++)
|
|
if(linkflag[a] && (tf->flag & TF_SELECT))
|
|
break;
|
|
|
|
if (a<me->totface) {
|
|
for(a=0, tf=me->mtface; a<me->totface; a++, tf++)
|
|
if(linkflag[a])
|
|
tf->flag &= ~TF_SELECT;
|
|
}
|
|
else {
|
|
for(a=0, tf=me->mtface; a<me->totface; a++, tf++)
|
|
if(linkflag[a])
|
|
tf->flag |= TF_SELECT;
|
|
}
|
|
}
|
|
|
|
MEM_freeN(linkflag);
|
|
|
|
BIF_undo_push("Select linked UV face");
|
|
object_tface_flags_changed(OBACT, 0);
|
|
}
|
|
|
|
/* Parametrizer */
|
|
|
|
ParamHandle *construct_param_handle(Mesh *me, short implicit, short fill, short sel)
|
|
{
|
|
int a;
|
|
MTFace *tf;
|
|
MFace *mf;
|
|
MVert *mv;
|
|
MEdge *medge;
|
|
ParamHandle *handle;
|
|
|
|
handle = param_construct_begin();
|
|
|
|
mv= me->mvert;
|
|
mf= me->mface;
|
|
tf= me->mtface;
|
|
for (a=0; a<me->totface; a++, mf++, tf++) {
|
|
ParamKey key, vkeys[4];
|
|
ParamBool pin[4], select[4];
|
|
float *co[4];
|
|
float *uv[4];
|
|
int nverts;
|
|
|
|
if (tf->flag & TF_HIDE)
|
|
continue;
|
|
|
|
if (sel && !(tf->flag & TF_SELECT))
|
|
continue;
|
|
|
|
if (implicit && !(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
|
|
continue;
|
|
|
|
key = (ParamKey)mf;
|
|
vkeys[0] = (ParamKey)mf->v1;
|
|
vkeys[1] = (ParamKey)mf->v2;
|
|
vkeys[2] = (ParamKey)mf->v3;
|
|
|
|
co[0] = (mv+mf->v1)->co;
|
|
co[1] = (mv+mf->v2)->co;
|
|
co[2] = (mv+mf->v3)->co;
|
|
|
|
uv[0] = tf->uv[0];
|
|
uv[1] = tf->uv[1];
|
|
uv[2] = tf->uv[2];
|
|
|
|
pin[0] = ((tf->unwrap & TF_PIN1) != 0);
|
|
pin[1] = ((tf->unwrap & TF_PIN2) != 0);
|
|
pin[2] = ((tf->unwrap & TF_PIN3) != 0);
|
|
|
|
select[0] = ((tf->flag & TF_SEL1) != 0);
|
|
select[1] = ((tf->flag & TF_SEL2) != 0);
|
|
select[2] = ((tf->flag & TF_SEL3) != 0);
|
|
|
|
if (mf->v4) {
|
|
vkeys[3] = (ParamKey)mf->v4;
|
|
co[3] = (mv+mf->v4)->co;
|
|
uv[3] = tf->uv[3];
|
|
pin[3] = ((tf->unwrap & TF_PIN4) != 0);
|
|
select[3] = ((tf->flag & TF_SEL4) != 0);
|
|
nverts = 4;
|
|
}
|
|
else
|
|
nverts = 3;
|
|
|
|
param_face_add(handle, key, nverts, vkeys, co, uv, pin, select);
|
|
}
|
|
|
|
if (!implicit) {
|
|
for(medge=me->medge, a=me->totedge; a>0; a--, medge++) {
|
|
if(medge->flag & ME_SEAM) {
|
|
ParamKey vkeys[2];
|
|
|
|
vkeys[0] = (ParamKey)medge->v1;
|
|
vkeys[1] = (ParamKey)medge->v2;
|
|
param_edge_set_seam(handle, vkeys);
|
|
}
|
|
}
|
|
}
|
|
|
|
param_construct_end(handle, fill, implicit);
|
|
|
|
return handle;
|
|
}
|
|
|
|
void unwrap_lscm(short seamcut)
|
|
{
|
|
Mesh *me;
|
|
ParamHandle *handle;
|
|
short abf = G.scene->toolsettings->unwrapper == 1;
|
|
short fillholes = G.scene->toolsettings->uvcalc_flag & 1;
|
|
|
|
me= get_mesh(OBACT);
|
|
if(me==0 || me->mtface==0) return;
|
|
|
|
handle = construct_param_handle(me, 0, fillholes, seamcut == 0);
|
|
|
|
param_lscm_begin(handle, PARAM_FALSE, abf);
|
|
param_lscm_solve(handle);
|
|
param_lscm_end(handle);
|
|
|
|
param_pack(handle);
|
|
|
|
param_flush(handle);
|
|
|
|
param_delete(handle);
|
|
|
|
if (!seamcut)
|
|
BIF_undo_push("UV unwrap");
|
|
|
|
object_uvs_changed(OBACT);
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
allqueue(REDRAWIMAGE, 0);
|
|
}
|
|
|
|
void minimize_stretch_tface_uv(void)
|
|
{
|
|
Mesh *me;
|
|
ParamHandle *handle;
|
|
double lasttime;
|
|
short doit = 1, escape = 0, val, blend = 0;
|
|
unsigned short event = 0;
|
|
short fillholes = G.scene->toolsettings->uvcalc_flag & 1;
|
|
|
|
me = get_mesh(OBACT);
|
|
if(me==0 || me->mtface==0) return;
|
|
|
|
handle = construct_param_handle(me, 1, fillholes, 1);
|
|
|
|
lasttime = PIL_check_seconds_timer();
|
|
|
|
param_stretch_begin(handle);
|
|
|
|
while (doit) {
|
|
param_stretch_iter(handle);
|
|
|
|
while (qtest()) {
|
|
event= extern_qread(&val);
|
|
|
|
if (val) {
|
|
switch (event) {
|
|
case ESCKEY:
|
|
escape = 1;
|
|
case RETKEY:
|
|
case PADENTER:
|
|
doit = 0;
|
|
break;
|
|
case PADPLUSKEY:
|
|
case WHEELUPMOUSE:
|
|
if (blend < 10) {
|
|
blend++;
|
|
param_stretch_blend(handle, blend*0.1f);
|
|
param_flush(handle);
|
|
lasttime = 0.0f;
|
|
}
|
|
break;
|
|
case PADMINUS:
|
|
case WHEELDOWNMOUSE:
|
|
if (blend > 0) {
|
|
blend--;
|
|
param_stretch_blend(handle, blend*0.1f);
|
|
param_flush(handle);
|
|
lasttime = 0.0f;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if ((event == LEFTMOUSE) || (event == RIGHTMOUSE)) {
|
|
escape = (event == RIGHTMOUSE);
|
|
doit = 0;
|
|
}
|
|
}
|
|
|
|
if (!doit)
|
|
break;
|
|
|
|
if (PIL_check_seconds_timer() - lasttime > 0.5) {
|
|
char str[100];
|
|
|
|
param_flush(handle);
|
|
|
|
sprintf(str, "Stretch minimize. Blend %.2f.", blend*0.1f);
|
|
headerprint(str);
|
|
|
|
lasttime = PIL_check_seconds_timer();
|
|
object_uvs_changed(OBACT);
|
|
if(G.sima->lock) force_draw_plus(SPACE_VIEW3D, 0);
|
|
else force_draw(0);
|
|
}
|
|
}
|
|
|
|
if (escape)
|
|
param_flush_restore(handle);
|
|
else
|
|
param_flush(handle);
|
|
|
|
param_stretch_end(handle);
|
|
|
|
param_delete(handle);
|
|
|
|
BIF_undo_push("UV stretch minimize");
|
|
|
|
object_uvs_changed(OBACT);
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
allqueue(REDRAWIMAGE, 0);
|
|
}
|
|
|
|
void pack_charts_tface_uv(void)
|
|
{
|
|
Mesh *me;
|
|
ParamHandle *handle;
|
|
|
|
me = get_mesh(OBACT);
|
|
if(me==0 || me->mtface==0) return;
|
|
|
|
handle = construct_param_handle(me, 1, 0, 1);
|
|
param_pack(handle);
|
|
param_flush(handle);
|
|
param_delete(handle);
|
|
|
|
BIF_undo_push("UV pack charts");
|
|
|
|
object_uvs_changed(OBACT);
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
allqueue(REDRAWIMAGE, 0);
|
|
}
|
|
|
|
/* LSCM live mode */
|
|
|
|
static ParamHandle *liveHandle = NULL;
|
|
|
|
void unwrap_lscm_live_begin(void)
|
|
{
|
|
Mesh *me;
|
|
short abf = G.scene->toolsettings->unwrapper == 1;
|
|
short fillholes = G.scene->toolsettings->uvcalc_flag & 1;
|
|
|
|
me= get_mesh(OBACT);
|
|
if(me==0 || me->mtface==0) return;
|
|
|
|
liveHandle = construct_param_handle(me, 0, fillholes, 1);
|
|
|
|
param_lscm_begin(liveHandle, PARAM_TRUE, abf);
|
|
}
|
|
|
|
void unwrap_lscm_live_re_solve(void)
|
|
{
|
|
if (liveHandle) {
|
|
param_lscm_solve(liveHandle);
|
|
param_flush(liveHandle);
|
|
}
|
|
}
|
|
|
|
void unwrap_lscm_live_end(short cancel)
|
|
{
|
|
if (liveHandle) {
|
|
param_lscm_end(liveHandle);
|
|
if (cancel)
|
|
param_flush_restore(liveHandle);
|
|
param_delete(liveHandle);
|
|
liveHandle = NULL;
|
|
}
|
|
}
|
|
|