#ifdef HAVE_CONFIG_H #include <config.h> #endif Just need to finish cpp files now :) Kent -- mein@cs.umn.edu
3985 lines
83 KiB
C
3985 lines
83 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 <math.h>
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#ifndef WIN32
|
|
#include <unistd.h>
|
|
#else
|
|
#include <io.h>
|
|
#include "BLI_winstuff.h"
|
|
#endif
|
|
#include <stdlib.h>
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "BMF_Api.h"
|
|
|
|
#include "BLI_blenlib.h"
|
|
#include "BLI_arithb.h"
|
|
#include "BLI_editVert.h"
|
|
|
|
#include "DNA_curve_types.h"
|
|
#include "DNA_ipo_types.h"
|
|
#include "DNA_key_types.h"
|
|
#include "DNA_mesh_types.h"
|
|
#include "DNA_object_types.h"
|
|
#include "DNA_scene_types.h"
|
|
#include "DNA_screen_types.h"
|
|
#include "DNA_view3d_types.h"
|
|
|
|
#include "BKE_utildefines.h"
|
|
#include "BKE_library.h"
|
|
#include "BKE_ipo.h"
|
|
#include "BKE_displist.h"
|
|
#include "BKE_curve.h"
|
|
#include "BKE_global.h"
|
|
#include "BKE_object.h"
|
|
#include "BKE_main.h"
|
|
|
|
#include "BIF_gl.h"
|
|
#include "BIF_graphics.h"
|
|
#include "BIF_screen.h"
|
|
#include "BIF_toolbox.h"
|
|
#include "BIF_space.h"
|
|
#include "BIF_editkey.h"
|
|
#include "BIF_mywindow.h"
|
|
#include "BIF_interface.h"
|
|
|
|
#include "BSE_view.h" /* For persp... */
|
|
#include "BSE_edit.h"
|
|
|
|
#include "BDR_drawobject.h"
|
|
#include "BDR_editcurve.h"
|
|
#include "BDR_editobject.h"
|
|
|
|
/* #include "graphics.h" */
|
|
#include "interface.h" /* MAART: for NUM and FLO types, + pupmenu */
|
|
/* #include "edit.h" */
|
|
#include "mydevice.h"
|
|
#include "blendef.h"
|
|
|
|
|
|
#include "BDR_editcurve.h"
|
|
/* still need to eradicate a few :( */
|
|
#define callocstructN(x,y,name) (x*)MEM_callocN((y)* sizeof(x),name)
|
|
/* only used sparingly: */
|
|
#define BEZSELECTED(bezt) (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
|
|
|
|
|
|
ListBase editNurb;
|
|
BPoint *lastselbp;
|
|
Nurb *lastnu; /* voor selected */
|
|
|
|
|
|
/* void freeNurblist(ListBase *lb); already declared in the kernel */
|
|
|
|
float nurbcircle[8][2]= {
|
|
{0.0, -1.0}, {-1.0, -1.0}, {-1.0, 0.0}, {-1.0, 1.0},
|
|
{0.0, 1.0}, { 1.0, 1.0}, { 1.0, 0.0}, { 1.0, -1.0}
|
|
};
|
|
|
|
short isNurbsel(Nurb *nu)
|
|
{
|
|
BezTriple *bezt;
|
|
BPoint *bp;
|
|
int a;
|
|
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
bezt= nu->bezt;
|
|
a= nu->pntsu;
|
|
while(a--) {
|
|
if( (bezt->f1 & 1) || (bezt->f2 & 1) || (bezt->f3 & 1) ) return 1;
|
|
bezt++;
|
|
}
|
|
}
|
|
else {
|
|
bp= nu->bp;
|
|
a= nu->pntsu*nu->pntsv;
|
|
while(a--) {
|
|
if( (bp->f1 & 1) ) return 1;
|
|
bp++;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int isNurbsel_count(Nurb *nu)
|
|
{
|
|
BezTriple *bezt;
|
|
BPoint *bp;
|
|
int a, sel=0;
|
|
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
bezt= nu->bezt;
|
|
a= nu->pntsu;
|
|
while(a--) {
|
|
if( (bezt->f1 & 1) || (bezt->f2 & 1) || (bezt->f3 & 1) ) sel++;
|
|
bezt++;
|
|
}
|
|
}
|
|
else {
|
|
bp= nu->bp;
|
|
a= nu->pntsu*nu->pntsv;
|
|
while(a--) {
|
|
if( (bp->f1 & 1) ) sel++;
|
|
bp++;
|
|
}
|
|
}
|
|
return sel;
|
|
}
|
|
|
|
|
|
void printknots()
|
|
{
|
|
Nurb *nu;
|
|
int a, num;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if(isNurbsel(nu) && (nu->type & 7)==CU_NURBS) {
|
|
if(nu->knotsu) {
|
|
num= KNOTSU(nu);
|
|
for(a=0;a<num;a++) printf("knotu %d: %f\n", a, nu->knotsu[a]);
|
|
}
|
|
if(nu->knotsv) {
|
|
num= KNOTSV(nu);
|
|
for(a=0;a<num;a++) printf("knotv %d: %f\n", a, nu->knotsv[a]);
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
static void printweightsNurb(void)
|
|
{
|
|
Nurb *nu;
|
|
BPoint *bp;
|
|
int a;
|
|
char str[30];
|
|
|
|
if(G.obedit==0) return;
|
|
|
|
persp(0);
|
|
|
|
glDrawBuffer(GL_FRONT);
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if((nu->type & 7)==CU_NURBS) {
|
|
a= nu->pntsu*nu->pntsv;
|
|
bp= nu->bp;
|
|
while(a--) {
|
|
if(bp->f1 & 1) {
|
|
if(bp->s[0]!= 3200) {
|
|
sprintf(str,"%2.2f", bp->vec[3]);
|
|
|
|
cpack(0x737373);
|
|
glRasterPos2i(bp->s[0]-1, bp->s[1]-1);
|
|
BMF_DrawString(G.font, str);
|
|
|
|
glRasterPos2i(bp->s[0]+1, bp->s[1]+1);
|
|
BMF_DrawString(G.font, str);
|
|
|
|
cpack(0xFFFFFF);
|
|
glRasterPos2i(bp->s[0], bp->s[1]);
|
|
BMF_DrawString(G.font, str);
|
|
}
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
|
|
glDrawBuffer(GL_BACK);
|
|
persp(1);
|
|
}
|
|
#endif
|
|
|
|
|
|
/* ********************* LOAD EN MAKE *************** */
|
|
|
|
void load_editNurb()
|
|
{
|
|
/* laad editNurb in object */
|
|
Curve *cu= 0;
|
|
Nurb *nu, *newnu;
|
|
KeyBlock *actkey=0;
|
|
|
|
if(G.obedit==0) return;
|
|
|
|
if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
|
|
|
|
G.totvert= count_curveverts(&editNurb);
|
|
|
|
cu= G.obedit->data;
|
|
|
|
/* zijn er keys? */
|
|
if(cu->key) {
|
|
actkey= cu->key->block.first;
|
|
while(actkey) {
|
|
if(actkey->flag & SELECT) break;
|
|
actkey= actkey->next;
|
|
}
|
|
|
|
if(actkey) {
|
|
/* aktieve key: de vertices */
|
|
|
|
if(G.totvert) {
|
|
if(actkey->data) MEM_freeN(actkey->data);
|
|
|
|
actkey->data= MEM_callocN(cu->key->elemsize*G.totvert, "actkey->data");
|
|
actkey->totelem= G.totvert;
|
|
|
|
curve_to_key(cu, actkey, &editNurb);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(cu->key && actkey!=cu->key->refkey) {
|
|
/* er zijn keys, alleen veranderingen in verts schrijven */
|
|
/* als aantal vertices verschillen, beetje onvoorspelbaar */
|
|
|
|
/* vertex -> vertex copy! */
|
|
if(actkey) key_to_curve(actkey, cu, &cu->nurb);
|
|
}
|
|
else {
|
|
freeNurblist(&(cu->nurb));
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
newnu= duplicateNurb(nu);
|
|
newnu->hide= 0;
|
|
BLI_addtail(&(cu->nurb), newnu);
|
|
|
|
if((nu->type & 7)==CU_NURBS) {
|
|
if(nu->pntsu < nu->orderu) nu->orderu= nu->pntsu;
|
|
}
|
|
|
|
nu= nu->next;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
lastnu= 0; /* voor selected */
|
|
|
|
}
|
|
|
|
void make_editNurb()
|
|
{
|
|
/* maak kopie van baseNurb in editNurb */
|
|
Curve *cu=0;
|
|
Nurb *nu, *newnu;
|
|
BezTriple *bezt;
|
|
BPoint *bp;
|
|
KeyBlock *actkey=0;
|
|
int a, tot=0;
|
|
|
|
if(G.obedit==0) return;
|
|
|
|
lastselbp= 0; /* global voor select row */
|
|
|
|
if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
|
|
freeNurblist(&editNurb);
|
|
|
|
cu= G.obedit->data;
|
|
nu= cu->nurb.first;
|
|
|
|
while(nu) {
|
|
newnu= duplicateNurb(nu);
|
|
BLI_addtail(&editNurb, newnu);
|
|
/* flags op nul */
|
|
newnu->hide= 0;
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
a= nu->pntsu;
|
|
bezt= newnu->bezt;
|
|
while(a--) {
|
|
bezt->f1= bezt->f2= bezt->f3= bezt->hide= 0;
|
|
bezt++;
|
|
tot+= 3;
|
|
}
|
|
}
|
|
else {
|
|
a= nu->pntsu*nu->pntsv;
|
|
bp= newnu->bp;
|
|
while(a--) {
|
|
bp->f1= bp->hide= 0;
|
|
bp++;
|
|
tot++;
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
|
|
if(cu->key) {
|
|
actkey= cu->key->block.first;
|
|
while(actkey) {
|
|
if(actkey->flag & SELECT) break;
|
|
actkey= actkey->next;
|
|
}
|
|
|
|
if(actkey) {
|
|
key_to_curve(actkey, cu, &editNurb);
|
|
}
|
|
}
|
|
makeDispList(G.obedit);
|
|
}
|
|
else G.obedit= 0;
|
|
|
|
countall();
|
|
|
|
lastnu= 0; /* voor selected */
|
|
}
|
|
|
|
void remake_editNurb()
|
|
{
|
|
|
|
if(okee("Reload Original data")==0) return;
|
|
|
|
make_editNurb();
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
allqueue(REDRAWBUTSEDIT, 0);
|
|
}
|
|
|
|
|
|
void separate_nurb()
|
|
{
|
|
Nurb *nu, *nu1;
|
|
Object *oldob;
|
|
Base *base, *oldbase;
|
|
Curve *cu;
|
|
ListBase editnurbo;
|
|
float trans[9];
|
|
|
|
if( (G.vd->lay & G.obedit->lay)==0 ) return;
|
|
|
|
if(okee("Separate")==0) return;
|
|
|
|
waitcursor(1);
|
|
|
|
cu= G.obedit->data;
|
|
if(cu->key) {
|
|
error("Can't separate with vertex keys");
|
|
return;
|
|
}
|
|
|
|
/* we gaan de zaak als volgt neppen:
|
|
* 1. duplicate base: dit wordt de nieuwe, oude pointer onthouden
|
|
* 2. alle NIET geselecteerde curves/nurbs apart zetten
|
|
* 3. load_ebaseNurb(): dit is de nieuwe base
|
|
* 4. freelist en oude nurbs weer terughalen
|
|
*/
|
|
|
|
/* alleen ebase geselecteerd */
|
|
base= FIRSTBASE;
|
|
while(base) {
|
|
if(base->lay & G.vd->lay) {
|
|
if(base->object==G.obedit) base->flag |= 1;
|
|
else base->flag &= ~1;
|
|
}
|
|
base= base->next;
|
|
}
|
|
|
|
/* apart zetten: alles wat maar enigszins NIET select is */
|
|
editnurbo.first= editnurbo.last= 0;
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
nu1= nu->next;
|
|
if(isNurbsel(nu)==0) {
|
|
BLI_remlink(&editNurb, nu);
|
|
BLI_addtail(&editnurbo, nu);
|
|
}
|
|
nu= nu1;
|
|
}
|
|
|
|
oldob= G.obedit;
|
|
oldbase= BASACT;
|
|
|
|
trans[0]=trans[1]=trans[2]=trans[3]=trans[4]=trans[5]= 0.0;
|
|
trans[6]=trans[7]=trans[8]= 1.0;
|
|
G.qual |= LR_ALTKEY; /* patch om zeker te zijn van gelinkte dupli */
|
|
adduplicate(trans);
|
|
G.qual &= ~LR_ALTKEY;
|
|
|
|
G.obedit= BASACT->object; /* basact wordt in adduplicate() gezet */
|
|
|
|
G.obedit->data= copy_curve(cu);
|
|
/* omdat nieuwe curve een kopie is: aantal users verlagen */
|
|
cu->id.us--;
|
|
|
|
load_editNurb();
|
|
|
|
BASACT->flag &= ~SELECT;
|
|
|
|
if(editNurb.first) freeNurblist(&editNurb);
|
|
|
|
editNurb= editnurbo;
|
|
|
|
G.obedit= 0; /* displisten doen anders in editmode */
|
|
makeDispList(OBACT); /* de gesepareerde */
|
|
|
|
G.obedit= oldob;
|
|
BASACT= oldbase;
|
|
BASACT->flag |= SELECT;
|
|
|
|
waitcursor(0);
|
|
|
|
countall();
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
lastnu= 0; /* voor selected */
|
|
}
|
|
|
|
/* ******************* FLAGS ********************* */
|
|
|
|
|
|
short isNurbselUV(Nurb *nu, int *u, int *v, int flag)
|
|
/*
|
|
Nurb *nu;
|
|
int *u, *v, flag;
|
|
*/
|
|
{
|
|
/* return u!=-1: 1 rij in u-richting geselecteerd. U heeft de waarde tussen 0-pntsv
|
|
* return v!=-1: 1 kolom in v-richting geselecteerd. V heeft de waarde tussen 0-pntsu
|
|
*/
|
|
BPoint *bp;
|
|
int a, b, sel;
|
|
|
|
*u= *v= -1;
|
|
|
|
bp= nu->bp;
|
|
for(b=0; b<nu->pntsv; b++) {
|
|
sel= 0;
|
|
for(a=0; a<nu->pntsu; a++, bp++) {
|
|
if(bp->f1 & flag) sel++;
|
|
}
|
|
if(sel==nu->pntsu) {
|
|
if(*u== -1) *u= b;
|
|
else return 0;
|
|
}
|
|
else if(sel>1) return 0; /* want sel==1 is nog goed */
|
|
}
|
|
|
|
for(a=0; a<nu->pntsu; a++) {
|
|
sel= 0;
|
|
bp= nu->bp+a;
|
|
for(b=0; b<nu->pntsv; b++, bp+=nu->pntsu) {
|
|
if(bp->f1 & flag) sel++;
|
|
}
|
|
if(sel==nu->pntsv) {
|
|
if(*v== -1) *v= a;
|
|
else return 0;
|
|
}
|
|
else if(sel>1) return 0;
|
|
}
|
|
|
|
if(*u==-1 && *v>-1) return 1;
|
|
if(*v==-1 && *u>-1) return 1;
|
|
return 0;
|
|
}
|
|
|
|
void setflagsNurb(short flag)
|
|
/* short flag; */
|
|
{
|
|
Nurb *nu;
|
|
BezTriple *bezt;
|
|
BPoint *bp;
|
|
int a;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if( (nu->type & 7)==CU_BEZIER) {
|
|
a= nu->pntsu;
|
|
bezt= nu->bezt;
|
|
while(a--) {
|
|
bezt->f1= bezt->f2= bezt->f3= flag;
|
|
bezt++;
|
|
}
|
|
}
|
|
else {
|
|
a= nu->pntsu*nu->pntsv;
|
|
bp= nu->bp;
|
|
while(a--) {
|
|
bp->f1= flag;
|
|
bp++;
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
}
|
|
|
|
void rotateflagNurb(short flag, float *cent, float rotmat[][3])
|
|
{
|
|
/* alle verts met (flag & 'flag') rotate */
|
|
Nurb *nu;
|
|
BPoint *bp;
|
|
int a;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if((nu->type & 7)==CU_NURBS) {
|
|
bp= nu->bp;
|
|
a= nu->pntsu*nu->pntsv;
|
|
|
|
while(a--) {
|
|
if(bp->f1 & flag) {
|
|
bp->vec[0]-=cent[0];
|
|
bp->vec[1]-=cent[1];
|
|
bp->vec[2]-=cent[2];
|
|
Mat3MulVecfl(rotmat, bp->vec);
|
|
bp->vec[0]+=cent[0];
|
|
bp->vec[1]+=cent[1];
|
|
bp->vec[2]+=cent[2];
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
}
|
|
|
|
|
|
void translateflagNurb(short flag, float *vec)
|
|
{
|
|
/* alle verts met (->f & flag) translate */
|
|
Nurb *nu;
|
|
BezTriple *bezt;
|
|
BPoint *bp;
|
|
int a;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if( (nu->type & 7)==CU_BEZIER) {
|
|
a= nu->pntsu;
|
|
bezt= nu->bezt;
|
|
while(a--) {
|
|
if(bezt->f1 & flag) VecAddf(bezt->vec[0], bezt->vec[0], vec);
|
|
if(bezt->f2 & flag) VecAddf(bezt->vec[1], bezt->vec[1], vec);
|
|
if(bezt->f3 & flag) VecAddf(bezt->vec[2], bezt->vec[2], vec);
|
|
bezt++;
|
|
}
|
|
}
|
|
else {
|
|
a= nu->pntsu*nu->pntsv;
|
|
bp= nu->bp;
|
|
while(a--) {
|
|
if(bp->f1 & flag) VecAddf(bp->vec, bp->vec, vec);
|
|
bp++;
|
|
}
|
|
}
|
|
|
|
test2DNurb(nu);
|
|
|
|
nu= nu->next;
|
|
}
|
|
}
|
|
|
|
void weightflagNurb(short flag, float w, int mode) /* mode==0: vervangen, mode==1: vermenigvuldigen */
|
|
{
|
|
Nurb *nu;
|
|
BPoint *bp;
|
|
int a;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if((nu->type & 7)==CU_NURBS) {
|
|
a= nu->pntsu*nu->pntsv;
|
|
bp= nu->bp;
|
|
while(a--) {
|
|
if(bp->f1 & flag) {
|
|
if(mode==1) bp->vec[3]*= w;
|
|
else bp->vec[3]= w;
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
}
|
|
|
|
void deleteflagNurb(short flag)
|
|
{
|
|
Nurb *nu, *next;
|
|
BPoint *bp, *bpn, *newbp;
|
|
int a, b, newu, newv, sel;
|
|
|
|
if(G.obedit && G.obedit->type==OB_SURF);
|
|
else return;
|
|
|
|
lastselbp= 0;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
next= nu->next;
|
|
|
|
/* is de hele nurb geselecteerd */
|
|
bp= nu->bp;
|
|
a= nu->pntsu*nu->pntsv;
|
|
while(a) {
|
|
a--;
|
|
if(bp->f1 & flag);
|
|
else break;
|
|
bp++;
|
|
}
|
|
if(a==0) {
|
|
BLI_remlink(&editNurb, nu);
|
|
freeNurb(nu);
|
|
}
|
|
else {
|
|
/* is de nurb in U richting geselecteerd */
|
|
newv= nu->pntsv;
|
|
bp= nu->bp;
|
|
for(b=0; b<nu->pntsv; b++) {
|
|
sel= 0;
|
|
for(a=0; a<nu->pntsu; a++, bp++) {
|
|
if(bp->f1 & flag) sel++;
|
|
}
|
|
if(sel==nu->pntsu) {
|
|
newv--;
|
|
}
|
|
else if(sel>=1) {
|
|
/* don't delete */
|
|
break;
|
|
}
|
|
}
|
|
if(newv!=nu->pntsv && b==nu->pntsv) {
|
|
/* deleten */
|
|
bp= nu->bp;
|
|
bpn = newbp =
|
|
(BPoint*) MEM_mallocN(newv * nu->pntsu * sizeof(BPoint), "deleteNurb");
|
|
for(b=0; b<nu->pntsv; b++) {
|
|
if((bp->f1 & flag)==0) {
|
|
memcpy(bpn, bp, nu->pntsu*sizeof(BPoint));
|
|
bpn+= nu->pntsu;
|
|
}
|
|
bp+= nu->pntsu;
|
|
}
|
|
nu->pntsv= newv;
|
|
MEM_freeN(nu->bp);
|
|
nu->bp= newbp;
|
|
if(nu->orderv>nu->pntsv) nu->orderv= nu->pntsv;
|
|
|
|
makeknots(nu, 2, nu->flagv>>1);
|
|
}
|
|
else {
|
|
/* is de nurb in V richting geselecteerd */
|
|
newu= nu->pntsu;
|
|
for(a=0; a<nu->pntsu; a++) {
|
|
bp= nu->bp+a;
|
|
sel= 0;
|
|
for(b=0; b<nu->pntsv; b++, bp+=nu->pntsu) {
|
|
if(bp->f1 & flag) sel++;
|
|
}
|
|
if(sel==nu->pntsv) {
|
|
newu--;
|
|
}
|
|
else if(sel>=1) {
|
|
/* don't delete */
|
|
break;
|
|
}
|
|
}
|
|
if(newu!=nu->pntsu && a==nu->pntsu) {
|
|
/* deleten */
|
|
bp= nu->bp;
|
|
bpn = newbp =
|
|
(BPoint*) MEM_mallocN(newu * nu->pntsv * sizeof(BPoint), "deleteNurb");
|
|
for(b=0; b<nu->pntsv; b++) {
|
|
for(a=0; a<nu->pntsu; a++, bp++) {
|
|
if((bp->f1 & flag)==0) {
|
|
*bpn= *bp;
|
|
bpn++;
|
|
}
|
|
}
|
|
}
|
|
MEM_freeN(nu->bp);
|
|
nu->bp= newbp;
|
|
if(newu==1 && nu->pntsv>1) { /* maak een U spline */
|
|
nu->pntsu= nu->pntsv;
|
|
nu->pntsv= 1;
|
|
SWAP(short, nu->orderu, nu->orderv);
|
|
if(nu->orderu>nu->pntsu) nu->orderu= nu->pntsu;
|
|
if(nu->knotsv) MEM_freeN(nu->knotsv);
|
|
nu->knotsv= 0;
|
|
}
|
|
else {
|
|
nu->pntsu= newu;
|
|
if(nu->orderu>nu->pntsu) nu->orderu= nu->pntsu;
|
|
}
|
|
makeknots(nu, 1, nu->flagu>>1);
|
|
}
|
|
}
|
|
}
|
|
nu= next;
|
|
}
|
|
}
|
|
|
|
short extrudeflagNurb(int flag)
|
|
/* int flag; */
|
|
{
|
|
Nurb *nu;
|
|
BPoint *bp, *bpn, *newbp;
|
|
int ok= 0, a, u, v, len;
|
|
|
|
if(G.obedit && G.obedit->type==OB_SURF);
|
|
else return 0;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
|
|
if(nu->pntsv==1) {
|
|
bp= nu->bp;
|
|
a= nu->pntsu;
|
|
while(a) {
|
|
if(bp->f1 & flag);
|
|
else break;
|
|
bp++;
|
|
a--;
|
|
}
|
|
if(a==0) {
|
|
ok= 1;
|
|
newbp =
|
|
(BPoint*)MEM_mallocN(2 * nu->pntsu * sizeof(BPoint), "extrudeNurb1");
|
|
memcpy(newbp, nu->bp, nu->pntsu*sizeof(BPoint) );
|
|
bp= newbp+ nu->pntsu;
|
|
memcpy(bp, nu->bp, nu->pntsu*sizeof(BPoint) );
|
|
MEM_freeN(nu->bp);
|
|
nu->bp= newbp;
|
|
a= nu->pntsu;
|
|
while(a--) {
|
|
bp->f1 |= flag;
|
|
newbp->f1 &= ~flag;
|
|
bp++;
|
|
newbp++;
|
|
}
|
|
|
|
nu->pntsv= 2;
|
|
nu->orderv= 2;
|
|
makeknots(nu, 2, nu->flagv>>1);
|
|
}
|
|
}
|
|
else {
|
|
/* welke rij of kolom is geselecteerd */
|
|
|
|
if( isNurbselUV(nu, &u, &v, flag) ) {
|
|
|
|
/* alles deselecteren */
|
|
bp= nu->bp;
|
|
a= nu->pntsu*nu->pntsv;
|
|
while(a--) {
|
|
bp->f1 &= ~flag;
|
|
bp++;
|
|
}
|
|
|
|
if(u==0 || u== nu->pntsv-1) { /* rij in u-richting geselecteerd */
|
|
ok= 1;
|
|
newbp =
|
|
(BPoint*) MEM_mallocN(nu->pntsu*(nu->pntsv + 1)
|
|
* sizeof(BPoint), "extrudeNurb1");
|
|
if(u==0) {
|
|
len= nu->pntsv*nu->pntsu;
|
|
memcpy(newbp+nu->pntsu, nu->bp, len*sizeof(BPoint) );
|
|
memcpy(newbp, nu->bp, nu->pntsu*sizeof(BPoint) );
|
|
bp= newbp;
|
|
}
|
|
else {
|
|
len= nu->pntsv*nu->pntsu;
|
|
memcpy(newbp, nu->bp, len*sizeof(BPoint) );
|
|
memcpy(newbp+len, nu->bp+len-nu->pntsu, nu->pntsu*sizeof(BPoint) );
|
|
bp= newbp+len;
|
|
}
|
|
|
|
a= nu->pntsu;
|
|
while(a--) {
|
|
bp->f1 |= flag;
|
|
bp++;
|
|
}
|
|
|
|
MEM_freeN(nu->bp);
|
|
nu->bp= newbp;
|
|
nu->pntsv++;
|
|
if(nu->resolv<3) nu->resolv++;
|
|
makeknots(nu, 2, nu->flagv>>1);
|
|
}
|
|
else if(v==0 || v== nu->pntsu-1) { /* kolom in v-richting geselecteerd */
|
|
ok= 1;
|
|
bpn = newbp =
|
|
(BPoint*) MEM_mallocN((nu->pntsu + 1) * nu->pntsv * sizeof(BPoint), "extrudeNurb1");
|
|
bp= nu->bp;
|
|
|
|
for(a=0; a<nu->pntsv; a++) {
|
|
if(v==0) {
|
|
*bpn= *bp;
|
|
bpn->f1 |= flag;
|
|
bpn++;
|
|
}
|
|
memcpy(bpn, bp, nu->pntsu*sizeof(BPoint));
|
|
bp+= nu->pntsu;
|
|
bpn+= nu->pntsu;
|
|
if(v== nu->pntsu-1) {
|
|
*bpn= *(bp-1);
|
|
bpn->f1 |= flag;
|
|
bpn++;
|
|
}
|
|
}
|
|
|
|
MEM_freeN(nu->bp);
|
|
nu->bp= newbp;
|
|
nu->pntsu++;
|
|
if(nu->resolu<3) nu->resolu++;
|
|
makeknots(nu, 1, nu->flagu>>1);
|
|
}
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
|
|
void adduplicateflagNurb(short flag)
|
|
/* short flag; */
|
|
{
|
|
Nurb *nu, *newnu;
|
|
BezTriple *bezt, *bezt1;
|
|
BPoint *bp, *bp1;
|
|
int a, b, starta, enda, newu, newv;
|
|
char *usel;
|
|
|
|
nu= editNurb.last;
|
|
while(nu) {
|
|
if( (nu->type & 7)==CU_BEZIER) {
|
|
bezt= nu->bezt;
|
|
for(a=0; a<nu->pntsu; a++) {
|
|
enda= -1;
|
|
starta= a;
|
|
while( (bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag) ) {
|
|
bezt->f1 &= ~flag;
|
|
bezt->f2 &= ~flag;
|
|
bezt->f3 &= ~flag;
|
|
enda=a;
|
|
if(a>=nu->pntsu-1) break;
|
|
a++;
|
|
bezt++;
|
|
}
|
|
if(enda>=starta) {
|
|
newnu = (Nurb*)MEM_mallocN(sizeof(Nurb), "adduplicateN");
|
|
memcpy(newnu, nu, sizeof(Nurb));
|
|
BLI_addtail(&editNurb, newnu);
|
|
lastnu= newnu;
|
|
newnu->pntsu= enda-starta+1;
|
|
newnu->bezt=
|
|
(BezTriple*)MEM_mallocN((enda - starta + 1) * sizeof(BezTriple), "adduplicateN");
|
|
memcpy(newnu->bezt, nu->bezt+starta, newnu->pntsu*sizeof(BezTriple));
|
|
|
|
b= newnu->pntsu;
|
|
bezt1= newnu->bezt;
|
|
while(b--) {
|
|
bezt1->f1 |= flag;
|
|
bezt1->f2 |= flag;
|
|
bezt1->f3 |= flag;
|
|
bezt1++;
|
|
}
|
|
|
|
if(nu->flagu & 1) {
|
|
if(starta!=0 || enda!=nu->pntsu-1) newnu->flagu--;
|
|
}
|
|
}
|
|
bezt++;
|
|
}
|
|
}
|
|
else if(nu->pntsv==1) { /* want UV Nurb heeft andere duplimethode */
|
|
bp= nu->bp;
|
|
for(a=0; a<nu->pntsu; a++) {
|
|
enda= -1;
|
|
starta= a;
|
|
while(bp->f1 & flag) {
|
|
bp->f1 &= ~flag;
|
|
enda= a;
|
|
if(a>=nu->pntsu-1) break;
|
|
a++;
|
|
bp++;
|
|
}
|
|
if(enda>=starta) {
|
|
newnu = (Nurb*)MEM_mallocN(sizeof(Nurb), "adduplicateN3");
|
|
memcpy(newnu, nu, sizeof(Nurb));
|
|
lastnu= newnu;
|
|
BLI_addtail(&editNurb, newnu);
|
|
newnu->pntsu= enda-starta+1;
|
|
newnu->bp = (BPoint*)MEM_mallocN((enda-starta+1) * sizeof(BPoint), "adduplicateN4");
|
|
memcpy(newnu->bp, nu->bp+starta, newnu->pntsu*sizeof(BPoint));
|
|
|
|
b= newnu->pntsu;
|
|
bp1= newnu->bp;
|
|
while(b--) {
|
|
bp1->f1 |= flag;
|
|
bp1++;
|
|
}
|
|
|
|
if(nu->flagu & 1) {
|
|
if(starta!=0 || enda!=nu->pntsu-1) newnu->flagu--;
|
|
}
|
|
|
|
/* knots */
|
|
newnu->knotsu= 0;
|
|
makeknots(newnu, 1, newnu->flagu>>1);
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
else {
|
|
/* een rechthoekig gebied in de nurb moet geselecteerd zijn */
|
|
if(isNurbsel(nu)) {
|
|
usel= MEM_callocN(nu->pntsu, "adduplicateN4");
|
|
bp= nu->bp;
|
|
for(a=0; a<nu->pntsv; a++) {
|
|
for(b=0; b<nu->pntsu; b++, bp++) {
|
|
if(bp->f1 & flag) usel[b]++;
|
|
}
|
|
}
|
|
newu= 0;
|
|
newv= 0;
|
|
for(a=0; a<nu->pntsu; a++) {
|
|
if(usel[a]) {
|
|
if(newv==0 || usel[a]==newv) {
|
|
newv= usel[a];
|
|
newu++;
|
|
}
|
|
else {
|
|
newv= 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(newu==0 || newv==0) {
|
|
printf("Can't duplicate Nurb\n");
|
|
}
|
|
else {
|
|
|
|
if(newu==1) SWAP(short, newu, newv);
|
|
|
|
newnu = (Nurb*)MEM_mallocN(sizeof(Nurb), "adduplicateN5");
|
|
memcpy(newnu, nu, sizeof(Nurb));
|
|
BLI_addtail(&editNurb, newnu);
|
|
lastnu= newnu;
|
|
newnu->pntsu= newu;
|
|
newnu->pntsv= newv;
|
|
newnu->bp =
|
|
(BPoint*)MEM_mallocN(newu * newv * sizeof(BPoint), "adduplicateN6");
|
|
newnu->orderu= MIN2(nu->orderu, newu);
|
|
newnu->orderv= MIN2(nu->orderv, newv);
|
|
|
|
bp= newnu->bp;
|
|
bp1= nu->bp;
|
|
for(a=0; a<nu->pntsv; a++) {
|
|
for(b=0; b<nu->pntsu; b++, bp1++) {
|
|
if(bp1->f1 & flag) {
|
|
memcpy(bp, bp1, sizeof(BPoint));
|
|
bp1->f1 &= ~flag;
|
|
bp++;
|
|
}
|
|
}
|
|
}
|
|
if(nu->pntsu==newnu->pntsu) {
|
|
newnu->knotsu= MEM_mallocN(sizeof(float)*KNOTSU(nu), "adduplicateN6");
|
|
memcpy(newnu->knotsu, nu->knotsu, sizeof(float)*KNOTSU(nu));
|
|
}
|
|
else {
|
|
newnu->knotsu= 0;
|
|
makeknots(newnu, 1, newnu->flagu>>1);
|
|
}
|
|
if(nu->pntsv==newnu->pntsv) {
|
|
newnu->knotsv= MEM_mallocN(sizeof(float)*KNOTSV(nu), "adduplicateN7");
|
|
memcpy(newnu->knotsv, nu->knotsv, sizeof(float)*KNOTSV(nu));
|
|
}
|
|
else {
|
|
newnu->knotsv= 0;
|
|
makeknots(newnu, 2, newnu->flagv>>1);
|
|
}
|
|
|
|
}
|
|
MEM_freeN(usel);
|
|
}
|
|
}
|
|
|
|
nu= nu->prev;
|
|
}
|
|
|
|
/* lastnu changed */
|
|
allqueue(REDRAWBUTSEDIT, 0);
|
|
}
|
|
|
|
|
|
void switchdirectionNurb2(void)
|
|
{
|
|
Nurb *nu;
|
|
|
|
if(G.obedit->lay & G.vd->lay);
|
|
else return;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if( isNurbsel(nu) ) switchdirectionNurb(nu);
|
|
nu= nu->next;
|
|
}
|
|
|
|
makeDispList(G.obedit);
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
|
|
void switchdirection_knots(float *base, int tot)
|
|
{
|
|
float *fp1, *fp2, *tempf;
|
|
int a;
|
|
|
|
if(base==NULL || tot==0) return;
|
|
|
|
/* de knots omkeren */
|
|
a= tot;
|
|
fp1= base;
|
|
fp2= fp1+(a-1);
|
|
a/= 2;
|
|
while(fp1!=fp2 && a>0) {
|
|
SWAP(float, *fp1, *fp2);
|
|
a--;
|
|
fp1++;
|
|
fp2--;
|
|
}
|
|
/* en weer in stijgende lijn maken */
|
|
a= tot;
|
|
fp1= base;
|
|
fp2=tempf= MEM_mallocN(sizeof(float)*a, "switchdirect");
|
|
while(a--) {
|
|
fp2[0]= fabs(fp1[1]-fp1[0]);
|
|
fp1++;
|
|
fp2++;
|
|
}
|
|
|
|
a= tot-1;
|
|
fp1= base;
|
|
fp2= tempf;
|
|
fp1[0]= 0.0;
|
|
fp1++;
|
|
while(a--) {
|
|
fp1[0]= fp1[-1]+fp2[0];
|
|
fp1++;
|
|
fp2++;
|
|
}
|
|
MEM_freeN(tempf);
|
|
}
|
|
|
|
/* **************** EDIT ************************ */
|
|
|
|
void deselectall_nurb()
|
|
{
|
|
Nurb *nu;
|
|
BezTriple *bezt;
|
|
BPoint *bp;
|
|
int a, b;
|
|
|
|
if(G.obedit->lay & G.vd->lay);
|
|
else return;
|
|
|
|
a= 0;
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
b= nu->pntsu;
|
|
bezt= nu->bezt;
|
|
while(b--) {
|
|
if(bezt->hide==0) {
|
|
if(bezt->f1 & 1) {
|
|
a=1;
|
|
break;
|
|
}
|
|
if(bezt->f2 & 1) {
|
|
a=1;
|
|
break;
|
|
}
|
|
if(bezt->f3 & 1) {
|
|
a=1;
|
|
break;
|
|
}
|
|
}
|
|
bezt++;
|
|
}
|
|
}
|
|
else {
|
|
b= nu->pntsu*nu->pntsv;
|
|
bp= nu->bp;
|
|
while(b--) {
|
|
if(bp->hide==0) {
|
|
if(bp->f1 & 1) {
|
|
a=1;
|
|
break;
|
|
}
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
if(a) break;
|
|
nu= nu->next;
|
|
}
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if((nu->type & 7)==1) {
|
|
b= nu->pntsu;
|
|
bezt= nu->bezt;
|
|
while(b--) {
|
|
if(bezt->hide==0) {
|
|
if(a) {
|
|
bezt->f1 &= ~1;
|
|
bezt->f2 &= ~1;
|
|
bezt->f3 &= ~1;
|
|
}
|
|
else {
|
|
bezt->f1 |= 1;
|
|
bezt->f2 |= 1;
|
|
bezt->f3 |= 1;
|
|
}
|
|
}
|
|
bezt++;
|
|
}
|
|
}
|
|
else {
|
|
b= nu->pntsu*nu->pntsv;
|
|
bp= nu->bp;
|
|
while(b--) {
|
|
if(bp->hide==0) {
|
|
if(a) bp->f1 &= ~ 1;
|
|
else bp->f1 |= 1;
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
countall();
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
|
|
void hideNurb(int swap)
|
|
{
|
|
Nurb *nu;
|
|
BPoint *bp;
|
|
BezTriple *bezt;
|
|
int a, sel;
|
|
|
|
if(G.obedit==0) return;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
bezt= nu->bezt;
|
|
a= nu->pntsu;
|
|
sel= 0;
|
|
while(a--) {
|
|
if(BEZSELECTED(bezt)) {
|
|
sel++;
|
|
bezt->f1 &= ~1;
|
|
bezt->f2 &= ~1;
|
|
bezt->f3 &= ~1;
|
|
bezt->hide= 1;
|
|
}
|
|
bezt++;
|
|
}
|
|
if(sel==nu->pntsu) nu->hide= 1;
|
|
}
|
|
else {
|
|
bp= nu->bp;
|
|
a= nu->pntsu*nu->pntsv;
|
|
sel= 0;
|
|
while(a--) {
|
|
if(swap==0 && (bp->f1 & 1)) {
|
|
bp->f1 &= ~1;
|
|
bp->hide= 1;
|
|
sel++;
|
|
}
|
|
else if(swap && (bp->f1 & 1)==0) {
|
|
bp->f1 &= ~1;
|
|
bp->hide= 1;
|
|
sel++;
|
|
}
|
|
bp++;
|
|
}
|
|
if(sel==nu->pntsu*nu->pntsv) nu->hide= 1;
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
|
|
makeDispList(G.obedit);
|
|
countall();
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
|
|
void revealNurb()
|
|
{
|
|
Nurb *nu;
|
|
BPoint *bp;
|
|
BezTriple *bezt;
|
|
int a;
|
|
|
|
if(G.obedit==0) return;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
nu->hide= 0;
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
bezt= nu->bezt;
|
|
a= nu->pntsu;
|
|
while(a--) {
|
|
if(bezt->hide) {
|
|
bezt->f1 |= 1;
|
|
bezt->f2 |= 1;
|
|
bezt->f3 |= 1;
|
|
bezt->hide= 0;
|
|
}
|
|
bezt++;
|
|
}
|
|
}
|
|
else {
|
|
bp= nu->bp;
|
|
a= nu->pntsu*nu->pntsv;
|
|
while(a--) {
|
|
if(bp->hide) {
|
|
bp->f1 |= 1;
|
|
bp->hide= 0;
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
|
|
makeDispList(G.obedit);
|
|
countall();
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
|
|
void selectswapNurb()
|
|
{
|
|
Nurb *nu;
|
|
BPoint *bp;
|
|
BezTriple *bezt;
|
|
int a;
|
|
|
|
if(G.obedit==0) return;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
bezt= nu->bezt;
|
|
a= nu->pntsu;
|
|
while(a--) {
|
|
if(bezt->hide==0) {
|
|
if(bezt->f1 & 1) bezt->f1 &= ~1;
|
|
else bezt->f1 |= 1;
|
|
if(bezt->f2 & 1) bezt->f2 &= ~1;
|
|
else bezt->f2 |= 1;
|
|
if(bezt->f3 & 1) bezt->f3 &= ~1;
|
|
else bezt->f3 |= 1;
|
|
}
|
|
bezt++;
|
|
}
|
|
}
|
|
else {
|
|
bp= nu->bp;
|
|
a= nu->pntsu*nu->pntsv;
|
|
while(a--) {
|
|
if(bp->hide==0) {
|
|
if(bp->f1 & 1) bp->f1 &= ~1;
|
|
else bp->f1 |= 1;
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
|
|
countall();
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
|
|
/** Divide the line segments associated with the currently selected
|
|
* curve nodes (Bezier or NURB). If there are no valid segment
|
|
* selections within the current selection, nothing happens.
|
|
*
|
|
* @deffunc subdividenurb subdivideNurb(void)
|
|
* @return Nothing
|
|
* @param None
|
|
*/
|
|
void subdivideNurb()
|
|
{
|
|
Nurb *nu;
|
|
BezTriple *prevbezt, *bezt, *beztnew, *beztn;
|
|
BPoint *bp, *prevbp, *bpnew, *bpn;
|
|
float vec[12];
|
|
int a, b, sel, aantal, *usel, *vsel;
|
|
|
|
// printf("*** subdivideNurb: entering subdivide\n");
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
aantal= 0;
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
/*
|
|
Insert a point into a 2D Bezier curve.
|
|
Endpoints are preserved. Otherwise, all selected and inserted points are
|
|
newly created. Old points are discarded.
|
|
*/
|
|
/* tellen */
|
|
if(nu->flagu & 1) {
|
|
a= nu->pntsu;
|
|
bezt= nu->bezt;
|
|
prevbezt= bezt+(a-1);
|
|
}
|
|
else {
|
|
a= nu->pntsu-1;
|
|
prevbezt= nu->bezt;
|
|
bezt= prevbezt+1;
|
|
}
|
|
while(a--) {
|
|
if( BEZSELECTED(prevbezt) && BEZSELECTED(bezt) ) aantal++;
|
|
prevbezt= bezt;
|
|
bezt++;
|
|
}
|
|
|
|
if(aantal) {
|
|
/* inserten */
|
|
beztnew =
|
|
/* I have some severe doubt about the original
|
|
* formulation... I stick to the upper bound to be
|
|
* on the safe side */
|
|
(BezTriple*)MEM_mallocN((aantal + nu->pntsu) * sizeof(BezTriple), "subdivNurb");
|
|
/* mallocstructN(BezTriple, aantal+nu->pntsu, "subdivNurb"); */
|
|
beztn= beztnew;
|
|
if(nu->flagu & 1) {
|
|
a= nu->pntsu;
|
|
bezt= nu->bezt;
|
|
prevbezt= bezt+(a-1);
|
|
}
|
|
else {
|
|
a= nu->pntsu-1;
|
|
prevbezt= nu->bezt;
|
|
bezt= prevbezt+1;
|
|
}
|
|
while(a--) {
|
|
memcpy(beztn, prevbezt, sizeof(BezTriple));
|
|
beztn++;
|
|
// printf("*** subdivideNurb: insert Bezier point\n");
|
|
|
|
if( BEZSELECTED(prevbezt) && BEZSELECTED(bezt) ) {
|
|
memcpy(beztn, bezt, sizeof(BezTriple));
|
|
maakbez(prevbezt->vec[1][0],prevbezt->vec[2][0],
|
|
bezt->vec[0][0],bezt->vec[1][0],vec,2);
|
|
maakbez(prevbezt->vec[1][1],prevbezt->vec[2][1],
|
|
bezt->vec[0][1],bezt->vec[1][1],vec+1,2);
|
|
maakbez(prevbezt->vec[1][2],prevbezt->vec[2][2],
|
|
bezt->vec[0][2],bezt->vec[1][2],vec+2,2);
|
|
VECCOPY(beztn->vec[1], vec+3);
|
|
beztn->h1= beztn->h2= HD_AUTO;
|
|
beztn++;
|
|
}
|
|
|
|
prevbezt= bezt;
|
|
bezt++;
|
|
}
|
|
/* laatste punt */
|
|
if((nu->flagu & 1)==0) memcpy(beztn, prevbezt, sizeof(BezTriple));
|
|
|
|
MEM_freeN(nu->bezt);
|
|
nu->bezt= beztnew;
|
|
nu->pntsu+= aantal;
|
|
|
|
calchandlesNurb(nu);
|
|
}
|
|
} /* End of 'if((nu->type & 7)==CU_BEZIER)' */
|
|
else if (nu->pntsv==1) {
|
|
/*
|
|
All flat lines (ie. co-planar), except flat Nurbs. Flat NURB curves
|
|
are handled together with the regular NURB plane division, as it
|
|
should be. I split it off just now, let's see if it is
|
|
stable... nzc 30-5-'00
|
|
*/
|
|
/* tellen */
|
|
if(nu->flagu & 1) {
|
|
a= nu->pntsu*nu->pntsv;
|
|
bp= nu->bp;
|
|
prevbp= bp+(a-1);
|
|
}
|
|
else {
|
|
a= nu->pntsu-1;
|
|
prevbp= nu->bp;
|
|
bp= prevbp+1;
|
|
}
|
|
while(a--) {
|
|
if( (bp->f1 & 1) && (prevbp->f1 & 1) ) aantal++;
|
|
prevbp= bp;
|
|
bp++;
|
|
}
|
|
|
|
if(aantal) {
|
|
/* inserten */
|
|
bpnew =
|
|
(BPoint*)MEM_mallocN((aantal + nu->pntsu) * sizeof(BPoint), "subdivNurb2");
|
|
bpn= bpnew;
|
|
|
|
if(nu->flagu & 1) {
|
|
a= nu->pntsu;
|
|
bp= nu->bp;
|
|
prevbp= bp+(a-1);
|
|
}
|
|
else {
|
|
a= nu->pntsu-1;
|
|
prevbp= nu->bp;
|
|
bp= prevbp+1;
|
|
}
|
|
while(a--) {
|
|
memcpy(bpn, prevbp, sizeof(BPoint));
|
|
bpn++;
|
|
|
|
if( (bp->f1 & 1) && (prevbp->f1 & 1) ) {
|
|
// printf("*** subdivideNurb: insert 'linear' point\n");
|
|
memcpy(bpn, bp, sizeof(BPoint));
|
|
bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
|
|
bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
|
|
bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
|
|
bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
|
|
bpn++;
|
|
|
|
}
|
|
prevbp= bp;
|
|
bp++;
|
|
}
|
|
if((nu->flagu & 1)==0) memcpy(bpn, prevbp, sizeof(BPoint)); /* laatste punt */
|
|
|
|
MEM_freeN(nu->bp);
|
|
nu->bp= bpnew;
|
|
nu->pntsu+= aantal;
|
|
|
|
if(nu->type & 4) {
|
|
makeknots(nu, 1, nu->flagu>>1);
|
|
}
|
|
}
|
|
} /* End of 'else if(nu->pntsv==1)' */
|
|
else if((nu->type & 7)==CU_NURBS) {
|
|
/* This is a very strange test ... */
|
|
/**
|
|
Subdivide NURB surfaces - nzc 30-5-'00 -
|
|
|
|
Subdivision of a NURB curve can be effected by adding a
|
|
control point (insertion of a knot), or by raising the
|
|
degree of the functions used to build the NURB. The
|
|
expression
|
|
|
|
degree = #knots - #controlpoints + 1 (J Walter piece)
|
|
degree = #knots - #controlpoints (Blender
|
|
implementation)
|
|
( this is confusing.... what is true? Another concern
|
|
is that the JW piece allows the curve to become
|
|
explicitly 1st order derivative discontinuous, while
|
|
this is not what we want here... )
|
|
|
|
is an invariant for a single NURB curve. Raising the degree
|
|
of the NURB is done elsewhere; the degree is assumed
|
|
constant during this opration. Degree is a property shared
|
|
by all controlpoints in a curve (even though it is stored
|
|
per control point - this can be misleading).
|
|
Adding a knot is done by searching for the place in the
|
|
knot vector where a certain knot value must be inserted, or
|
|
by picking an appropriate knot value between two existing
|
|
ones. The number of controlpoints that is influenced by the
|
|
insertion depends on the order of the curve. A certain
|
|
minimum number of knots is needed to form high-order
|
|
curves, as can be seen from the equation above. In Blender,
|
|
currently NURBs may be up to 6th order, so we modify at
|
|
most 6 points. One point is added. For an n-degree curve,
|
|
n points are discarded, and n+1 points inserted
|
|
(so effectively, n points are modified). (that holds for
|
|
the JW piece, but it seems not for our NURBs)
|
|
In practice, the knot spacing is copied, but the tail
|
|
(the points following the insertion point) need to be
|
|
offset to keep the knot series ascending. The knot series
|
|
is always a series of monotonically ascending integers in
|
|
Blender. When not enough control points are available to
|
|
fit the order, duplicates of the endpoints are added as
|
|
needed.
|
|
*/
|
|
/* selecteer-arrays aanleggen */
|
|
usel= MEM_callocN(sizeof(int)*nu->pntsu, "subivideNurb3");
|
|
vsel= MEM_callocN(sizeof(int)*nu->pntsv, "subivideNurb3");
|
|
sel= 0;
|
|
|
|
/* Count the number of selected points. */
|
|
bp= nu->bp;
|
|
for(a=0; a<nu->pntsv; a++) {
|
|
for(b=0; b<nu->pntsu; b++) {
|
|
if(bp->f1 & 1) {
|
|
usel[b]++;
|
|
vsel[a]++;
|
|
sel++;
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
if( sel == (nu->pntsu*nu->pntsv) ) { /* hele nurb subdividen */
|
|
/* Global subdivision is a special case of partial
|
|
subdivision. Strange it is considered separately... */
|
|
bpn=bpnew= MEM_mallocN( (2*nu->pntsu-1)*(2*nu->pntsv-1)*sizeof(BPoint), "subdivideNurb4");
|
|
bp= nu->bp;
|
|
/* eerst de rijen subdividen */
|
|
for(a=0; a<nu->pntsv; a++) {
|
|
for(b=0; b<nu->pntsu; b++) {
|
|
*bpn= *bp;
|
|
bpn++;
|
|
bp++;
|
|
if(b<nu->pntsu-1) {
|
|
*bpn= *bp;
|
|
prevbp= bp-1;
|
|
bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
|
|
bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
|
|
bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
|
|
bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
|
|
bpn++;
|
|
}
|
|
}
|
|
bpn+= (2*nu->pntsu-1);
|
|
}
|
|
/* nu nieuwe invoegen */
|
|
bpn= bpnew+(2*nu->pntsu-1);
|
|
bp= bpnew+(4*nu->pntsu-2);
|
|
prevbp= bpnew;
|
|
for(a=1; a<nu->pntsv; a++) {
|
|
|
|
for(b=0; b<2*nu->pntsu-1; b++) {
|
|
*bpn= *bp;
|
|
bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
|
|
bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
|
|
bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
|
|
bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
|
|
bpn++;
|
|
bp++;
|
|
prevbp++;
|
|
}
|
|
bp+= (2*nu->pntsu-1);
|
|
bpn+= (2*nu->pntsu-1);
|
|
prevbp+= (2*nu->pntsu-1);
|
|
}
|
|
MEM_freeN(nu->bp);
|
|
nu->bp= bpnew;
|
|
nu->pntsu= 2*nu->pntsu-1;
|
|
nu->pntsv= 2*nu->pntsv-1;
|
|
makeknots(nu, 1, nu->flagu>>1);
|
|
makeknots(nu, 2, nu->flagv>>1);
|
|
} /* End of 'if(sel== nu->pntsu*nu->pntsv)' (subdivide entire NURB) */
|
|
else {
|
|
/* in v richting subdividen? */
|
|
sel= 0;
|
|
for(a=0; a<nu->pntsv-1; a++) {
|
|
if(vsel[a]==nu->pntsu && vsel[a+1]==nu->pntsu) sel++;
|
|
}
|
|
|
|
if(sel) { /* V ! */
|
|
bpn=bpnew= MEM_mallocN( (sel+nu->pntsv)*nu->pntsu*sizeof(BPoint), "subdivideNurb4");
|
|
bp= nu->bp;
|
|
for(a=0; a<nu->pntsv; a++) {
|
|
for(b=0; b<nu->pntsu; b++) {
|
|
*bpn= *bp;
|
|
bpn++;
|
|
bp++;
|
|
}
|
|
if( (a<nu->pntsv-1) && vsel[a]==nu->pntsu && vsel[a+1]==nu->pntsu ) {
|
|
prevbp= bp- nu->pntsu;
|
|
for(b=0; b<nu->pntsu; b++) {
|
|
/*
|
|
This simple bisection must be replaces by a
|
|
subtle resampling of a number of points. Our
|
|
task is made slightly easier because each
|
|
point in our curve is a separate data
|
|
node. (is it?)
|
|
*/
|
|
*bpn= *prevbp;
|
|
bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
|
|
bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
|
|
bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
|
|
bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
|
|
bpn++;
|
|
prevbp++;
|
|
bp++;
|
|
}
|
|
bp-= nu->pntsu;
|
|
}
|
|
}
|
|
MEM_freeN(nu->bp);
|
|
nu->bp= bpnew;
|
|
nu->pntsv+= sel;
|
|
makeknots(nu, 2, nu->flagv>>1);
|
|
}
|
|
else {
|
|
/* of in u richting? */
|
|
sel= 0;
|
|
for(a=0; a<nu->pntsu-1; a++) {
|
|
if(usel[a]==nu->pntsv && usel[a+1]==nu->pntsv) sel++;
|
|
}
|
|
|
|
if(sel) { /* U ! */
|
|
/* Inserting U points is sort of 'default' Flat curves only get */
|
|
/* U points inserted in them. */
|
|
bpn=bpnew= MEM_mallocN( (sel+nu->pntsu)*nu->pntsv*sizeof(BPoint), "subdivideNurb4");
|
|
bp= nu->bp;
|
|
for(a=0; a<nu->pntsv; a++) {
|
|
for(b=0; b<nu->pntsu; b++) {
|
|
*bpn= *bp;
|
|
bpn++;
|
|
bp++;
|
|
if( (b<nu->pntsu-1) && usel[b]==nu->pntsv && usel[b+1]==nu->pntsv ) {
|
|
/*
|
|
One thing that bugs me here is that the
|
|
orders of things are not the same as in
|
|
the JW piece. Also, this implies that we
|
|
handle at most 3rd order curves? I miss
|
|
some symmetry here...
|
|
*/
|
|
prevbp= bp- 1;
|
|
*bpn= *prevbp;
|
|
bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
|
|
bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
|
|
bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
|
|
bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
|
|
bpn++;
|
|
}
|
|
}
|
|
}
|
|
MEM_freeN(nu->bp);
|
|
nu->bp= bpnew;
|
|
nu->pntsu+= sel;
|
|
makeknots(nu, 1, nu->flagu>>1); /* shift knots
|
|
forward */
|
|
}
|
|
}
|
|
}
|
|
MEM_freeN(usel);
|
|
MEM_freeN(vsel);
|
|
// printf("*** subdivideNurb: end of NURB splitting part\n");
|
|
} /* End of 'if((nu->type & 7)==CU_NURBS)' */
|
|
nu= nu->next;
|
|
}
|
|
|
|
/* Sync flushing */
|
|
// printf("*** subdivideNurb: subdivide done\n");
|
|
|
|
makeDispList(G.obedit);
|
|
countall();
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
|
|
|
|
short findnearestNurbvert(short sel, Nurb **nurb, BezTriple **bezt, BPoint **bp)
|
|
/*
|
|
short sel;
|
|
Nurb **nurb;
|
|
BezTriple **bezt;
|
|
BPoint **bp;
|
|
*/
|
|
{
|
|
/* sel==1: selected krijgen een nadeel */
|
|
/* in nurb en bezt of bp wordt nearest weggeschreven */
|
|
/* return 0 1 2: handlepunt */
|
|
Nurb *nu;
|
|
BezTriple *bezt1;
|
|
BPoint *bp1;
|
|
short dist= 100, temp, mval[2], a, hpoint=0;
|
|
|
|
*nurb= 0;
|
|
*bezt= 0;
|
|
*bp= 0;
|
|
|
|
/* projektie doen */
|
|
calc_nurbverts_ext(); /* drawobject.c */
|
|
|
|
getmouseco_areawin(mval);
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
bezt1= nu->bezt;
|
|
a= nu->pntsu;
|
|
while(a--) {
|
|
if(bezt1->hide==0) {
|
|
temp= abs(mval[0]- bezt1->s[0][0])+ abs(mval[1]- bezt1->s[0][1]);
|
|
if( (bezt1->f1 & 1)==sel) temp+=5;
|
|
if(temp<dist) {
|
|
hpoint=0;
|
|
*bezt=bezt1;
|
|
dist= temp;
|
|
*nurb= nu;
|
|
*bp= 0;
|
|
}
|
|
|
|
/* middelste punten een klein nadeel */
|
|
temp= 3+abs(mval[0]- bezt1->s[1][0])+ abs(mval[1]- bezt1->s[1][1]);
|
|
if( (bezt1->f2 & 1)==sel) temp+=5;
|
|
if(temp<dist) {
|
|
hpoint=1;
|
|
*bezt=bezt1;
|
|
dist= temp;
|
|
*nurb= nu;
|
|
*bp= 0;
|
|
}
|
|
|
|
temp= abs(mval[0]- bezt1->s[2][0])+ abs(mval[1]- bezt1->s[2][1]);
|
|
if( (bezt1->f3 & 1)==sel) temp+=5;
|
|
if(temp<dist) {
|
|
hpoint=2;
|
|
*bezt=bezt1;
|
|
dist= temp;
|
|
*nurb= nu;
|
|
*bp= 0;
|
|
}
|
|
}
|
|
bezt1++;
|
|
}
|
|
}
|
|
else {
|
|
bp1= nu->bp;
|
|
a= nu->pntsu*nu->pntsv;
|
|
while(a--) {
|
|
if(bp1->hide==0) {
|
|
temp= abs(mval[0]- bp1->s[0])+ abs(mval[1]- bp1->s[1]);
|
|
if( (bp1->f1 & 1)==sel) temp+=5;
|
|
if(temp<dist) {
|
|
hpoint=0;
|
|
*bp=bp1;
|
|
dist= temp;
|
|
*nurb= nu;
|
|
*bezt= 0;
|
|
}
|
|
}
|
|
bp1++;
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
|
|
return hpoint;
|
|
}
|
|
|
|
|
|
void findselectedNurbvert(Nurb **nu, BezTriple **bezt, BPoint **bp)
|
|
{
|
|
/* in nu en (bezt of bp) wordt selected weggeschreven als er 1 sel. is */
|
|
/* als er meer punten in 1 spline selected: alleen nu terug, bezt en bp zijn 0 */
|
|
Nurb *nu1;
|
|
BezTriple *bezt1;
|
|
BPoint *bp1;
|
|
int a;
|
|
|
|
*nu= 0;
|
|
*bezt= 0;
|
|
*bp= 0;
|
|
nu1= editNurb.first;
|
|
while(nu1) {
|
|
if((nu1->type & 7)==CU_BEZIER) {
|
|
bezt1= nu1->bezt;
|
|
a= nu1->pntsu;
|
|
while(a--) {
|
|
if( (bezt1->f1 & 1) || (bezt1->f2 & 1) || (bezt1->f3 & 1) ) {
|
|
if(*nu!=0 && *nu!= nu1) {
|
|
*nu= 0;
|
|
*bp= 0;
|
|
*bezt= 0;
|
|
return;
|
|
}
|
|
else if(*bezt || *bp) {
|
|
*bp= 0;
|
|
*bezt= 0;
|
|
}
|
|
else {
|
|
*bezt= bezt1;
|
|
*nu= nu1;
|
|
}
|
|
}
|
|
bezt1++;
|
|
}
|
|
}
|
|
else {
|
|
bp1= nu1->bp;
|
|
a= nu1->pntsu*nu1->pntsv;
|
|
while(a--) {
|
|
if( bp1->f1 & 1 ) {
|
|
if(*nu!=0 && *nu!= nu1) {
|
|
*bp= 0;
|
|
*bezt= 0;
|
|
*nu= 0;
|
|
return;
|
|
}
|
|
else if(*bezt || *bp) {
|
|
*bp= 0;
|
|
*bezt= 0;
|
|
}
|
|
else {
|
|
*bp= bp1;
|
|
*nu= nu1;
|
|
}
|
|
}
|
|
bp1++;
|
|
}
|
|
}
|
|
nu1= nu1->next;
|
|
}
|
|
}
|
|
|
|
void setsplinetype(short type)
|
|
/*
|
|
short type;
|
|
*/
|
|
{
|
|
Nurb *nu;
|
|
BezTriple *bezt;
|
|
BPoint *bp;
|
|
int a, c, nr;
|
|
|
|
if(type==CU_CARDINAL || type==CU_BSPLINE) {
|
|
error("Not implemented yet");
|
|
return;
|
|
}
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if(isNurbsel(nu)) {
|
|
|
|
if((nu->type & 7)==0) { /* Poly */
|
|
if(type==CU_BEZIER) { /* naar Bezier met vecthandles */
|
|
nr= nu->pntsu;
|
|
bezt =
|
|
(BezTriple*)MEM_callocN(nr * sizeof(BezTriple), "setsplinetype2");
|
|
nu->bezt= bezt;
|
|
a= nr;
|
|
bp= nu->bp;
|
|
while(a--) {
|
|
VECCOPY(bezt->vec[1], bp->vec);
|
|
bezt->f1=bezt->f2=bezt->f3= bp->f1;
|
|
bezt->h1= bezt->h2= HD_VECT;
|
|
bp++;
|
|
bezt++;
|
|
}
|
|
MEM_freeN(nu->bp);
|
|
nu->bp= 0;
|
|
nu->pntsu= nr;
|
|
nu->type &= ~7;
|
|
nu->type |= 1;
|
|
calchandlesNurb(nu);
|
|
}
|
|
else if(type==4) { /* naar Nurb */
|
|
nu->type &= ~7;
|
|
nu->type+= 4;
|
|
nu->orderu= 4;
|
|
nu->flagu &= 1;
|
|
nu->flagu += 4;
|
|
makeknots(nu, 1, nu->flagu>>1);
|
|
a= nu->pntsu*nu->pntsv;
|
|
bp= nu->bp;
|
|
while(a--) {
|
|
bp->vec[3]= 1.0;
|
|
bp++;
|
|
}
|
|
}
|
|
}
|
|
else if((nu->type & 7)==CU_BEZIER) { /* Bezier */
|
|
if(type==0 || type==4) { /* naar Poly of Nurb */
|
|
nr= 3*nu->pntsu;
|
|
nu->bp =
|
|
(BPoint*)MEM_callocN(nr * sizeof(BPoint), "setsplinetype");
|
|
a= nu->pntsu;
|
|
bezt= nu->bezt;
|
|
bp= nu->bp;
|
|
while(a--) {
|
|
if(type==0 && bezt->h1==HD_VECT && bezt->h2==HD_VECT) {
|
|
/* vectorhandle wordt 1 polyvert */
|
|
VECCOPY(bp->vec, bezt->vec[1]);
|
|
bp->vec[3]= 1.0;
|
|
bp->f1= bezt->f2;
|
|
nr-= 2;
|
|
bp++;
|
|
}
|
|
else {
|
|
for(c=0;c<3;c++) {
|
|
VECCOPY(bp->vec, bezt->vec[c]);
|
|
bp->vec[3]= 1.0;
|
|
if(c==0) bp->f1= bezt->f1;
|
|
else if(c==1) bp->f1= bezt->f2;
|
|
else bp->f1= bezt->f3;
|
|
bp++;
|
|
}
|
|
}
|
|
bezt++;
|
|
}
|
|
MEM_freeN(nu->bezt);
|
|
nu->bezt= 0;
|
|
nu->pntsu= nr;
|
|
nu->pntsv= 1;
|
|
nu->orderu= 4;
|
|
nu->orderv= 1;
|
|
nu->type &= ~7;
|
|
nu->type+= type;
|
|
if(nu->flagu & 1) c= nu->orderu-1;
|
|
else c= 0;
|
|
if(type== 4) {
|
|
nu->flagu &= 1;
|
|
nu->flagu += 4;
|
|
makeknots(nu, 1, nu->flagu>>1);
|
|
}
|
|
}
|
|
}
|
|
else if( (nu->type & 7)==CU_NURBS && G.obedit->type==OB_CURVE) {
|
|
if(type==0) { /* naar Poly */
|
|
nu->type &= ~7;
|
|
MEM_freeN(nu->knotsu);
|
|
nu->knotsu= 0;
|
|
if(nu->knotsv) MEM_freeN(nu->knotsv);
|
|
nu->knotsv= 0;
|
|
}
|
|
else if(type==CU_BEZIER) { /* naar Bezier */
|
|
nr= nu->pntsu/3;
|
|
bezt =
|
|
(BezTriple*)MEM_callocN(nr * sizeof(BezTriple), "setsplinetype2");
|
|
nu->bezt= bezt;
|
|
a= nr;
|
|
bp= nu->bp;
|
|
while(a--) {
|
|
VECCOPY(bezt->vec[0], bp->vec);
|
|
bezt->f1= bp->f1;
|
|
bp++;
|
|
VECCOPY(bezt->vec[1], bp->vec);
|
|
bezt->f2= bp->f1;
|
|
bp++;
|
|
VECCOPY(bezt->vec[2], bp->vec);
|
|
bezt->f3= bp->f1;
|
|
bp++;
|
|
bezt++;
|
|
}
|
|
MEM_freeN(nu->bp);
|
|
nu->bp= 0;
|
|
MEM_freeN(nu->knotsu);
|
|
nu->knotsu= 0;
|
|
nu->pntsu= nr;
|
|
nu->type &= ~7;
|
|
nu->type+= 1;
|
|
}
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
}
|
|
|
|
/* ******************** SKINNING LOFTING!!! ******************** */
|
|
|
|
void rotate_direction_nurb(Nurb *nu)
|
|
{
|
|
BPoint *bp1, *bp2, *temp;
|
|
int u, v;
|
|
|
|
SWAP(short, nu->pntsu, nu->pntsv);
|
|
SWAP(short, nu->orderu, nu->orderv);
|
|
SWAP(short, nu->resolu, nu->resolv);
|
|
SWAP(short, nu->flagu, nu->flagv);
|
|
|
|
SWAP(float *, nu->knotsu, nu->knotsv);
|
|
switchdirection_knots(nu->knotsv, KNOTSV(nu) );
|
|
|
|
temp= MEM_dupallocN(nu->bp);
|
|
bp1= nu->bp;
|
|
for(v=0; v<nu->pntsv; v++) {
|
|
for(u=0; u<nu->pntsu; u++, bp1++) {
|
|
bp2= temp + (nu->pntsu-u-1)*(nu->pntsv) + v;
|
|
*bp1= *bp2;
|
|
}
|
|
}
|
|
|
|
MEM_freeN(temp);
|
|
}
|
|
|
|
int is_u_selected(Nurb *nu, int u)
|
|
{
|
|
BPoint *bp;
|
|
int v;
|
|
|
|
/* what about resolu == 2? */
|
|
bp= nu->bp+u;
|
|
for(v=0; v<nu->pntsv-1; v++, bp+=nu->pntsu) {
|
|
if(v) if(bp->f1 & 1) return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* ******************************** */
|
|
|
|
typedef struct NurbSort {
|
|
struct NurbSort *next, *prev;
|
|
Nurb *nu;
|
|
float vec[3];
|
|
} NurbSort;
|
|
|
|
static ListBase nsortbase= {0, 0};
|
|
/* static NurbSort *nusmain; */ /* this var seems to go unused... at least in this file */
|
|
|
|
void make_selection_list_nurb()
|
|
{
|
|
ListBase nbase= {0, 0};
|
|
NurbSort *nus, *nustest, *headdo, *taildo;
|
|
Nurb *nu;
|
|
BPoint *bp;
|
|
float dist, headdist, taildist;
|
|
int a;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if( isNurbsel(nu) ) {
|
|
|
|
nus = (NurbSort*)MEM_callocN(sizeof(NurbSort), "sort");
|
|
BLI_addhead(&nbase, nus);
|
|
nus->nu= nu;
|
|
|
|
bp= nu->bp;
|
|
a= nu->pntsu;
|
|
while(a--) {
|
|
VecAddf(nus->vec, nus->vec, bp->vec);
|
|
bp++;
|
|
}
|
|
VecMulf(nus->vec, 1.0/(float)nu->pntsu);
|
|
|
|
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
|
|
/* just add the first one */
|
|
nus= nbase.first;
|
|
BLI_remlink(&nbase, nus);
|
|
BLI_addtail( &nsortbase, nus);
|
|
|
|
/* now add, either at head or tail, the closest one */
|
|
while(nbase.first) {
|
|
|
|
headdist= taildist= 1.0e30;
|
|
headdo= taildo= 0;
|
|
|
|
nustest= nbase.first;
|
|
while(nustest) {
|
|
dist= VecLenf(nustest->vec, ((NurbSort *)nsortbase.first)->vec);
|
|
|
|
if(dist<headdist) {
|
|
headdist= dist;
|
|
headdo= nustest;
|
|
}
|
|
dist= VecLenf(nustest->vec, ((NurbSort *)nsortbase.last)->vec);
|
|
|
|
if(dist<taildist) {
|
|
taildist= dist;
|
|
taildo= nustest;
|
|
}
|
|
nustest= nustest->next;
|
|
}
|
|
|
|
if(headdist<taildist) {
|
|
BLI_remlink(&nbase, headdo);
|
|
BLI_addhead(&nsortbase, headdo);
|
|
}
|
|
else {
|
|
BLI_remlink(&nbase, taildo);
|
|
BLI_addtail(&nsortbase, taildo);
|
|
}
|
|
}
|
|
}
|
|
|
|
void merge_2_nurb(Nurb *nu1, Nurb *nu2)
|
|
{
|
|
BPoint *bp, *bp1, *bp2, *temp;
|
|
float len1, len2;
|
|
int origu, u, v;
|
|
|
|
/* first nurbs will be changed to make u = resolu-1 selected */
|
|
/* 2nd nurbs will be changed to make u = 0 selected */
|
|
|
|
/* first nurbs: u = resolu-1 selected */
|
|
|
|
if( is_u_selected(nu1, nu1->pntsu-1) );
|
|
else {
|
|
rotate_direction_nurb(nu1);
|
|
if( is_u_selected(nu1, nu1->pntsu-1) );
|
|
else {
|
|
rotate_direction_nurb(nu1);
|
|
if( is_u_selected(nu1, nu1->pntsu-1) );
|
|
else {
|
|
rotate_direction_nurb(nu1);
|
|
if( is_u_selected(nu1, nu1->pntsu-1) );
|
|
else {
|
|
/* rotate again, now its OK! */
|
|
if(nu1->pntsv!=1) rotate_direction_nurb(nu1);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 2nd nurbs: u = 0 selected */
|
|
if( is_u_selected(nu2, 0) );
|
|
else {
|
|
rotate_direction_nurb(nu2);
|
|
if( is_u_selected(nu2, 0) );
|
|
else {
|
|
rotate_direction_nurb(nu2);
|
|
if( is_u_selected(nu2, 0) );
|
|
else {
|
|
rotate_direction_nurb(nu2);
|
|
if( is_u_selected(nu2, 0) );
|
|
else {
|
|
/* rotate again, now its OK! */
|
|
if(nu1->pntsu==1) rotate_direction_nurb(nu1);
|
|
if(nu2->pntsv!=1) rotate_direction_nurb(nu2);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( nu1->pntsv != nu2->pntsv ) {
|
|
error("resolution doesn't match");
|
|
return;
|
|
}
|
|
|
|
/* ok, now nu1 has the rightmost collumn and nu2 the leftmost collumn selected */
|
|
/* maybe we need a 'v' flip of nu2? */
|
|
|
|
bp1= nu1->bp+nu1->pntsu-1;
|
|
bp2= nu2->bp;
|
|
len1= 0.0;
|
|
|
|
for(v=0; v<nu1->pntsv; v++, bp1+=nu1->pntsu, bp2+=nu2->pntsu) {
|
|
len1+= VecLenf(bp1->vec, bp2->vec);
|
|
}
|
|
|
|
bp1= nu1->bp + nu1->pntsu-1;
|
|
bp2= nu2->bp + nu2->pntsu*(nu2->pntsv-1);
|
|
len2= 0.0;
|
|
|
|
for(v=0; v<nu1->pntsv; v++, bp1+=nu1->pntsu, bp2-=nu2->pntsu) {
|
|
len2+= VecLenf(bp1->vec, bp2->vec);
|
|
}
|
|
|
|
/* merge */
|
|
origu= nu1->pntsu;
|
|
nu1->pntsu+= nu2->pntsu;
|
|
nu1->resolu+= nu2->pntsu;
|
|
if(nu1->resolv < nu2->resolv) nu1->resolv= nu2->resolv;
|
|
if(nu1->orderu<3) nu1->orderu++;
|
|
if(nu1->orderv<3) nu1->orderv++;
|
|
temp= nu1->bp;
|
|
nu1->bp= MEM_mallocN(nu1->pntsu*nu1->pntsv*sizeof(BPoint), "mergeBP");
|
|
|
|
bp= nu1->bp;
|
|
bp1= temp;
|
|
|
|
for(v=0; v<nu1->pntsv; v++) {
|
|
|
|
/* switch direction? */
|
|
if(len1<len2) bp2= nu2->bp + v*nu2->pntsu;
|
|
else bp2= nu2->bp + (nu1->pntsv-v-1)*nu2->pntsu;
|
|
|
|
for(u=0; u<nu1->pntsu; u++, bp++) {
|
|
if(u<origu) {
|
|
*bp= *bp1; bp1++;
|
|
bp->f1 &= ~SELECT;
|
|
}
|
|
else {
|
|
*bp= *bp2; bp2++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* merge knots */
|
|
makeknots(nu1, 1, nu1->flagu>>1);
|
|
|
|
/* make knots, for merged curved for example */
|
|
makeknots(nu1, 2, nu1->flagv>>1);
|
|
|
|
MEM_freeN(temp);
|
|
BLI_remlink(&editNurb, nu2);
|
|
freeNurb(nu2);
|
|
}
|
|
|
|
void merge_nurb()
|
|
{
|
|
NurbSort *nus1, *nus2;
|
|
int ok= 1;
|
|
|
|
make_selection_list_nurb();
|
|
|
|
if(nsortbase.first == nsortbase.last) {
|
|
BLI_freelistN(&nsortbase);
|
|
error("Too few selections");
|
|
return;
|
|
}
|
|
|
|
nus1= nsortbase.first;
|
|
nus2= nus1->next;
|
|
|
|
/* resolution match, to avoid uv rotations */
|
|
if(nus1->nu->pntsv==1) {
|
|
if(nus1->nu->pntsu==nus2->nu->pntsu || nus1->nu->pntsu==nus2->nu->pntsv);
|
|
else ok= 0;
|
|
}
|
|
else if(nus2->nu->pntsv==1) {
|
|
if(nus2->nu->pntsu==nus1->nu->pntsu || nus2->nu->pntsu==nus1->nu->pntsv);
|
|
else ok= 0;
|
|
}
|
|
else if( nus1->nu->pntsu==nus2->nu->pntsu || nus1->nu->pntsv==nus2->nu->pntsv);
|
|
else if( nus1->nu->pntsu==nus2->nu->pntsv || nus1->nu->pntsv==nus2->nu->pntsu);
|
|
else {
|
|
ok= 0;
|
|
}
|
|
|
|
if(ok==0) {
|
|
error("resolution doesn't match");
|
|
BLI_freelistN(&nsortbase);
|
|
return;
|
|
}
|
|
|
|
while(nus2) {
|
|
merge_2_nurb(nus1->nu, nus2->nu);
|
|
nus2= nus2->next;
|
|
}
|
|
|
|
BLI_freelistN(&nsortbase);
|
|
|
|
makeDispList(G.obedit);
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
}
|
|
|
|
|
|
void addsegment_nurb()
|
|
{
|
|
/* voegt twee curves samen */
|
|
Nurb *nu, *nu1=0, *nu2=0;
|
|
BezTriple *bezt;
|
|
BPoint *bp;
|
|
float *fp, offset;
|
|
int a;
|
|
|
|
/* first decide if this is a surface merge! */
|
|
if(G.obedit->type==OB_SURF) nu= editNurb.first;
|
|
else nu= 0;
|
|
|
|
while(nu) {
|
|
if( isNurbsel(nu) ) {
|
|
|
|
if(nu->pntsu>1 && nu->pntsv>1) break;
|
|
if(isNurbsel_count(nu)>1) break;
|
|
if(isNurbsel_count(nu)==1) {
|
|
/* only 1 selected, not first or last, a little complex, but intuitive */
|
|
if(nu->pntsv==1) {
|
|
if( (nu->bp->f1 & 1) || ((nu->bp+nu->pntsu-1)->f1 & 1));
|
|
else break;
|
|
}
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
if(nu) {
|
|
merge_nurb();
|
|
return;
|
|
}
|
|
|
|
/* vind de beide nurben en punten, nu1 wordt achter nu2 gezet */
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if((nu->flagu & 1)==0) { /* niet cyclic */
|
|
if( (nu->type & 7)==CU_BEZIER ) {
|
|
bezt= nu->bezt;
|
|
if(nu1==0) {
|
|
if( BEZSELECTED(bezt) ) nu1= nu;
|
|
else {
|
|
bezt= bezt+(nu->pntsu-1);
|
|
if( BEZSELECTED(bezt) ) {
|
|
nu1= nu;
|
|
switchdirectionNurb(nu);
|
|
}
|
|
}
|
|
}
|
|
else if(nu2==0) {
|
|
if( BEZSELECTED(bezt) ) {
|
|
nu2= nu;
|
|
switchdirectionNurb(nu);
|
|
}
|
|
else {
|
|
bezt= bezt+(nu->pntsu-1);
|
|
if( BEZSELECTED(bezt) ) {
|
|
nu2= nu;
|
|
}
|
|
}
|
|
}
|
|
else break;
|
|
}
|
|
else if(nu->pntsv==1) {
|
|
bp= nu->bp;
|
|
if(nu1==0) {
|
|
if( bp->f1 & 1) nu1= nu;
|
|
else {
|
|
bp= bp+(nu->pntsu-1);
|
|
if( bp->f1 & 1 ) {
|
|
nu1= nu;
|
|
switchdirectionNurb(nu);
|
|
}
|
|
}
|
|
}
|
|
else if(nu2==0) {
|
|
if( bp->f1 & 1) {
|
|
nu2= nu;
|
|
switchdirectionNurb(nu);
|
|
}
|
|
else {
|
|
bp= bp+(nu->pntsu-1);
|
|
if( bp->f1 & 1 ) {
|
|
nu2= nu;
|
|
}
|
|
}
|
|
}
|
|
else break;
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
|
|
if((nu1 && nu2) && (nu1!=nu2)) {
|
|
if( nu1->type==nu2->type) {
|
|
if((nu1->type & 7)==CU_BEZIER) {
|
|
bezt =
|
|
(BezTriple*)MEM_mallocN((nu1->pntsu+nu2->pntsu) * sizeof(BezTriple), "addsegmentN");
|
|
memcpy(bezt, nu2->bezt, nu2->pntsu*sizeof(BezTriple));
|
|
memcpy(bezt+nu2->pntsu, nu1->bezt, nu1->pntsu*sizeof(BezTriple));
|
|
MEM_freeN(nu1->bezt);
|
|
nu1->bezt= bezt;
|
|
nu1->pntsu+= nu2->pntsu;
|
|
BLI_remlink(&editNurb, nu2);
|
|
freeNurb(nu2);
|
|
calchandlesNurb(nu1);
|
|
}
|
|
else {
|
|
bp =
|
|
(BPoint*)MEM_mallocN((nu1->pntsu+nu2->pntsu) * sizeof(BPoint), "addsegmentN2");
|
|
memcpy(bp, nu2->bp, nu2->pntsu*sizeof(BPoint) );
|
|
memcpy(bp+nu2->pntsu, nu1->bp, nu1->pntsu*sizeof(BPoint));
|
|
MEM_freeN(nu1->bp);
|
|
nu1->bp= bp;
|
|
|
|
a= nu1->pntsu+nu1->orderu;
|
|
|
|
nu1->pntsu+= nu2->pntsu;
|
|
BLI_remlink(&editNurb, nu2);
|
|
|
|
/* en de knots aaneenrijgen */
|
|
if((nu1->type & 7)==4) {
|
|
fp= MEM_mallocN(sizeof(float)*KNOTSU(nu1), "addsegment3");
|
|
memcpy(fp, nu1->knotsu, sizeof(float)*a);
|
|
MEM_freeN(nu1->knotsu);
|
|
nu1->knotsu= fp;
|
|
|
|
|
|
offset= nu1->knotsu[a-1] +1.0;
|
|
fp= nu1->knotsu+a;
|
|
for(a=0; a<nu2->pntsu; a++, fp++) {
|
|
if(nu2->knotsu)
|
|
*fp= offset+nu2->knotsu[a+1];
|
|
else
|
|
*fp = offset;
|
|
}
|
|
}
|
|
freeNurb(nu2);
|
|
}
|
|
}
|
|
makeDispList(G.obedit);
|
|
countall();
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
else error("Can't make segment");
|
|
}
|
|
|
|
void mouse_nurb()
|
|
{
|
|
Nurb *nu;
|
|
BezTriple *bezt=0;
|
|
BPoint *bp=0;
|
|
short hand;
|
|
|
|
hand= findnearestNurbvert(1, &nu, &bezt, &bp);
|
|
|
|
if(bezt || bp) {
|
|
if((G.qual & LR_SHIFTKEY)==0) {
|
|
|
|
setflagsNurb(0);
|
|
|
|
if(bezt) {
|
|
|
|
if(hand==1) {
|
|
bezt->f1|= 1;
|
|
bezt->f2|= 1;
|
|
bezt->f3|= 1;
|
|
}
|
|
else if(hand==0) bezt->f1|= 1;
|
|
else bezt->f3|= 1;
|
|
}
|
|
else {
|
|
lastselbp= bp;
|
|
bp->f1 |= 1;
|
|
}
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
else {
|
|
if(bezt) {
|
|
if(hand==1) {
|
|
if(bezt->f2 & 1) {
|
|
bezt->f1 &= ~1;
|
|
bezt->f2 &= ~1;
|
|
bezt->f3 &= ~1;
|
|
}
|
|
else {
|
|
bezt->f1 |= 1;
|
|
bezt->f2 |= 1;
|
|
bezt->f3 |= 1;
|
|
}
|
|
}
|
|
else if(hand==0) {
|
|
if(bezt->f1 & 1) {
|
|
bezt->f1 &= ~1;
|
|
}
|
|
else {
|
|
bezt->f1 |= 1;
|
|
}
|
|
}
|
|
else {
|
|
if(bezt->f3 & 1) {
|
|
bezt->f3 &= ~1;
|
|
}
|
|
else {
|
|
bezt->f3 |= 1;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if(bp->f1 & 1) bp->f1 &= ~1;
|
|
else {
|
|
bp->f1 |= 1;
|
|
lastselbp= bp;
|
|
}
|
|
}
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
}
|
|
|
|
countall();
|
|
}
|
|
|
|
rightmouse_transform();
|
|
|
|
if(nu!=lastnu) {
|
|
lastnu= nu;
|
|
allqueue(REDRAWBUTSEDIT, 0);
|
|
}
|
|
|
|
}
|
|
|
|
void spinNurb(float *dvec, short mode)
|
|
/* float *dvec; */
|
|
/* short mode; */ /* 0 is extrude, 1 is duplicate */
|
|
{
|
|
Nurb *nu;
|
|
float *curs, si,phi,n[3],q[4],cmat[3][3],tmat[3][3],imat[3][3];
|
|
float cent[3],bmat[3][3], rotmat[3][3], scalemat1[3][3], scalemat2[3][3];
|
|
float persmat[3][3], persinv[3][3];
|
|
short a,ok;
|
|
|
|
if(G.obedit==0 || G.obedit->type!=OB_SURF) return;
|
|
if( (G.vd->lay & G.obedit->lay)==0 ) return;
|
|
|
|
Mat3CpyMat4(persmat, G.vd->viewmat);
|
|
Mat3Inv(persinv, persmat);
|
|
|
|
/* imat en centrum en afmeting */
|
|
Mat3CpyMat4(bmat, G.obedit->obmat);
|
|
Mat3Inv(imat, bmat);
|
|
|
|
curs= give_cursor();
|
|
VECCOPY(cent, curs);
|
|
VecSubf(cent, cent, G.obedit->obmat[3]);
|
|
Mat3MulVecfl(imat,cent);
|
|
|
|
if(dvec) {
|
|
n[0]=n[1]= 0.0;
|
|
n[2]= 1.0;
|
|
} else {
|
|
n[0]= G.vd->viewinv[2][0];
|
|
n[1]= G.vd->viewinv[2][1];
|
|
n[2]= G.vd->viewinv[2][2];
|
|
Normalise(n);
|
|
}
|
|
|
|
phi= M_PI/8.0;
|
|
q[0]= cos(phi);
|
|
si= sin(phi);
|
|
q[1]= n[0]*si;
|
|
q[2]= n[1]*si;
|
|
q[3]= n[2]*si;
|
|
QuatToMat3(q, cmat);
|
|
Mat3MulMat3(tmat, cmat, bmat);
|
|
Mat3MulMat3(rotmat, imat, tmat);
|
|
|
|
Mat3One(scalemat1);
|
|
scalemat1[0][0]= sqrt(2.0);
|
|
scalemat1[1][1]= sqrt(2.0);
|
|
|
|
Mat3MulMat3(tmat,persmat,bmat);
|
|
Mat3MulMat3(cmat,scalemat1,tmat);
|
|
Mat3MulMat3(tmat,persinv,cmat);
|
|
Mat3MulMat3(scalemat1,imat,tmat);
|
|
|
|
Mat3One(scalemat2);
|
|
scalemat2[0][0]/= sqrt(2.0);
|
|
scalemat2[1][1]/= sqrt(2.0);
|
|
|
|
Mat3MulMat3(tmat,persmat,bmat);
|
|
Mat3MulMat3(cmat,scalemat2,tmat);
|
|
Mat3MulMat3(tmat,persinv,cmat);
|
|
Mat3MulMat3(scalemat2,imat,tmat);
|
|
|
|
ok= 1;
|
|
|
|
for(a=0;a<7;a++) {
|
|
if(mode==0) ok= extrudeflagNurb(1);
|
|
else adduplicateflagNurb(1);
|
|
if(ok==0) {
|
|
error("Can't spin");
|
|
break;
|
|
}
|
|
rotateflagNurb(1,cent,rotmat);
|
|
|
|
if(mode==0) {
|
|
if( (a & 1)==0 ) {
|
|
rotateflagNurb(1,cent,scalemat1);
|
|
weightflagNurb(1, 0.25*sqrt(2.0), 1);
|
|
}
|
|
else {
|
|
rotateflagNurb(1,cent,scalemat2);
|
|
weightflagNurb(1, 4.0/sqrt(2.0), 1);
|
|
}
|
|
}
|
|
if(dvec) {
|
|
Mat3MulVecfl(bmat,dvec);
|
|
translateflagNurb(1,dvec);
|
|
}
|
|
}
|
|
|
|
if(ok) {
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if(isNurbsel(nu)) {
|
|
nu->orderv= 4;
|
|
nu->flagv |= 1;
|
|
makeknots(nu, 2, nu->flagv>>1);
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
void addvert_Nurb(int mode)
|
|
{
|
|
Nurb *nu;
|
|
BezTriple *bezt, *newbezt = NULL;
|
|
BPoint *bp, *newbp = NULL;
|
|
float *curs, mat[3][3],imat[3][3], temp[3];
|
|
|
|
if(G.obedit==0) return;
|
|
if( (G.vd->lay & G.obedit->lay)==0 ) return;
|
|
|
|
if(mode=='e' && okee("Extrude")==0) return;
|
|
|
|
Mat3CpyMat4(mat, G.obedit->obmat);
|
|
Mat3Inv(imat,mat);
|
|
|
|
findselectedNurbvert(&nu, &bezt, &bp);
|
|
if(bezt==0 && bp==0) return;
|
|
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
/* welk bezpoint? */
|
|
if(bezt== nu->bezt) { /* eerste */
|
|
bezt->f1= bezt->f2= bezt->f3= 0;
|
|
newbezt =
|
|
(BezTriple*)MEM_callocN((nu->pntsu+1) * sizeof(BezTriple), "addvert_Nurb");
|
|
memcpy(newbezt+1, bezt, nu->pntsu*sizeof(BezTriple));
|
|
*newbezt= *bezt;
|
|
newbezt->f1= newbezt->f2= newbezt->f3= 1;
|
|
if(bezt->h1 & 1) newbezt->h1= newbezt->h2= HD_AUTO;
|
|
else newbezt->h1= newbezt->h2= HD_VECT;
|
|
VECCOPY(temp, bezt->vec[1]);
|
|
MEM_freeN(nu->bezt);
|
|
nu->bezt= newbezt;
|
|
bezt= newbezt+1;
|
|
}
|
|
else if(bezt== (nu->bezt+nu->pntsu-1)) { /* laatste */
|
|
bezt->f1= bezt->f2= bezt->f3= 0;
|
|
newbezt =
|
|
(BezTriple*)MEM_callocN((nu->pntsu+1) * sizeof(BezTriple), "addvert_Nurb");
|
|
memcpy(newbezt, nu->bezt, nu->pntsu*sizeof(BezTriple));
|
|
*(newbezt+nu->pntsu)= *bezt;
|
|
VECCOPY(temp, bezt->vec[1]);
|
|
MEM_freeN(nu->bezt);
|
|
nu->bezt= newbezt;
|
|
newbezt+= nu->pntsu;
|
|
newbezt->f1= newbezt->f2= newbezt->f3= 1;
|
|
if(newbezt->h2 & 1) newbezt->h1= newbezt->h2= HD_AUTO;
|
|
else newbezt->h1= newbezt->h2= HD_VECT;
|
|
bezt= nu->bezt+nu->pntsu-1;
|
|
}
|
|
else bezt= 0;
|
|
|
|
if(bezt) {
|
|
nu->pntsu++;
|
|
newbezt->s[1][0]= G.vd->mx;
|
|
newbezt->s[1][1]= G.vd->my;
|
|
|
|
if(mode=='e') {
|
|
VECCOPY(newbezt->vec[0], bezt->vec[0]);
|
|
VECCOPY(newbezt->vec[1], bezt->vec[1]);
|
|
VECCOPY(newbezt->vec[2], bezt->vec[2]);
|
|
}
|
|
else {
|
|
curs= give_cursor();
|
|
|
|
VECCOPY(newbezt->vec[1], curs);
|
|
VecSubf(newbezt->vec[1],newbezt->vec[1],G.obedit->obmat[3]);
|
|
Mat3MulVecfl(imat,newbezt->vec[1]);
|
|
VecSubf(temp, newbezt->vec[1],temp);
|
|
VecAddf(newbezt->vec[0], bezt->vec[0],temp);
|
|
VecAddf(newbezt->vec[2], bezt->vec[2],temp);
|
|
calchandlesNurb(nu);
|
|
}
|
|
}
|
|
}
|
|
else if(nu->pntsv==1) {
|
|
/* welk b-point? */
|
|
if(bp== nu->bp) { /* eerste */
|
|
bp->f1= 0;
|
|
newbp =
|
|
(BPoint*)MEM_callocN((nu->pntsu+1) * sizeof(BPoint), "addvert_Nurb3");
|
|
memcpy(newbp+1, bp, nu->pntsu*sizeof(BPoint));
|
|
*newbp= *bp;
|
|
newbp->f1= 1;
|
|
MEM_freeN(nu->bp);
|
|
nu->bp= newbp;
|
|
}
|
|
else if(bp== (nu->bp+nu->pntsu-1)) { /* laatste */
|
|
bp->f1= 0;
|
|
newbp =
|
|
(BPoint*)MEM_callocN((nu->pntsu+1) * sizeof(BPoint), "addvert_Nurb4");
|
|
memcpy(newbp, nu->bp, nu->pntsu*sizeof(BPoint));
|
|
*(newbp+nu->pntsu)= *bp;
|
|
MEM_freeN(nu->bp);
|
|
nu->bp= newbp;
|
|
newbp+= nu->pntsu;
|
|
newbp->f1= 1;
|
|
}
|
|
else bp= 0;
|
|
|
|
if(bp) {
|
|
nu->pntsu++;
|
|
newbp->s[0]= G.vd->mx;
|
|
newbp->s[1]= G.vd->my;
|
|
|
|
if(nu->resolu<3) nu->resolu++;
|
|
makeknots(nu, 1, nu->flagu>>1);
|
|
|
|
if(mode=='e') {
|
|
VECCOPY(newbp->vec, bp->vec);
|
|
}
|
|
else {
|
|
curs= give_cursor();
|
|
|
|
VECCOPY(newbp->vec, curs);
|
|
VecSubf(newbp->vec, newbp->vec, G.obedit->obmat[3]);
|
|
Mat3MulVecfl(imat,newbp->vec);
|
|
newbp->vec[3]= 1.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
test2DNurb(nu);
|
|
makeDispList(G.obedit);
|
|
countall();
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
if(mode=='e') transform('d');
|
|
else while(get_mbut()&R_MOUSE) BIF_wait_for_statechange();
|
|
}
|
|
|
|
void extrude_nurb()
|
|
{
|
|
Nurb *nu;
|
|
int ok= 0;
|
|
|
|
if(G.obedit && G.obedit->type==OB_SURF) {
|
|
|
|
/* first test: curve? */
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if(nu->pntsv==1 && isNurbsel_count(nu)==1 ) break;
|
|
nu= nu->next;
|
|
}
|
|
if(nu) {
|
|
addvert_Nurb('e');
|
|
}
|
|
else {
|
|
|
|
if(okee("Extrude")==0) return;
|
|
ok= extrudeflagNurb(1); /* '1'= flag */
|
|
|
|
if(ok) {
|
|
makeDispList(G.obedit);
|
|
countall();
|
|
transform('d');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void makecyclicNurb()
|
|
{
|
|
Nurb *nu;
|
|
BezTriple *bezt;
|
|
BPoint *bp;
|
|
float *fp;
|
|
int a, b, cyclmode=0;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if( nu->pntsu>1 || nu->pntsv>1) {
|
|
if( (nu->type & 7)==0 ) {
|
|
a= nu->pntsu;
|
|
bp= nu->bp;
|
|
while(a--) {
|
|
if( bp->f1 & 1 ) {
|
|
if(nu->flagu & 1) nu->flagu--;
|
|
else nu->flagu++;
|
|
break;
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
else if( (nu->type & 7)==CU_BEZIER ) {
|
|
a= nu->pntsu;
|
|
bezt= nu->bezt;
|
|
while(a--) {
|
|
if( BEZSELECTED(bezt) ) {
|
|
if(nu->flagu & 1) nu->flagu--;
|
|
else nu->flagu++;
|
|
break;
|
|
}
|
|
bezt++;
|
|
}
|
|
calchandlesNurb(nu);
|
|
}
|
|
else if(nu->pntsv==1 && (nu->type & 7)==CU_NURBS) {
|
|
a= nu->pntsu;
|
|
bp= nu->bp;
|
|
while(a--) {
|
|
if( bp->f1 & 1 ) {
|
|
if(nu->flagu & 1) nu->flagu--;
|
|
else {
|
|
nu->flagu++;
|
|
fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN");
|
|
b= (nu->orderu+nu->pntsu);
|
|
memcpy(fp, nu->knotsu, sizeof(float)*b);
|
|
MEM_freeN(nu->knotsu);
|
|
nu->knotsu= fp;
|
|
|
|
makeknots(nu, 1, 0); /* 1==u 0==uniform */
|
|
|
|
}
|
|
break;
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
else if(nu->type==CU_NURBS) {
|
|
if(cyclmode==0) {
|
|
cyclmode= pupmenu("Toggle %t|cyclic U%x1|cyclic V%x2");
|
|
if(cyclmode < 1) return;
|
|
}
|
|
a= nu->pntsu*nu->pntsv;
|
|
bp= nu->bp;
|
|
while(a--) {
|
|
|
|
if( bp->f1 & 1) {
|
|
if(cyclmode==1 && nu->pntsu>1) {
|
|
if(nu->flagu & 1) nu->flagu--;
|
|
else {
|
|
nu->flagu++;
|
|
fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN");
|
|
b= (nu->orderu+nu->pntsu);
|
|
memcpy(fp, nu->knotsu, sizeof(float)*b);
|
|
MEM_freeN(nu->knotsu);
|
|
nu->knotsu= fp;
|
|
|
|
makeknots(nu, 1, 0); /* 1==u 0==uniform */
|
|
}
|
|
}
|
|
if(cyclmode==2 && nu->pntsv>1) {
|
|
if(nu->flagv & 1) nu->flagv--;
|
|
else {
|
|
nu->flagv++;
|
|
fp= MEM_mallocN(sizeof(float)*KNOTSV(nu), "makecyclicN");
|
|
b= (nu->orderv+nu->pntsv);
|
|
memcpy(fp, nu->knotsv, sizeof(float)*b);
|
|
MEM_freeN(nu->knotsv);
|
|
nu->knotsv= fp;
|
|
|
|
makeknots(nu, 2, 0); /* 2==v 0==uniform */
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
bp++;
|
|
}
|
|
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
makeDispList(G.obedit);
|
|
}
|
|
|
|
void selectconnected_nurb()
|
|
{
|
|
Nurb *nu;
|
|
BezTriple *bezt;
|
|
BPoint *bp;
|
|
int a;
|
|
|
|
findnearestNurbvert(1, &nu, &bezt, &bp);
|
|
if(bezt) {
|
|
a= nu->pntsu;
|
|
bezt= nu->bezt;
|
|
while(a--) {
|
|
if(bezt->hide==0) {
|
|
if(G.qual & LR_SHIFTKEY) {
|
|
bezt->f1 &= ~1;
|
|
bezt->f2 &= ~1;
|
|
bezt->f3 &= ~1;
|
|
}
|
|
else {
|
|
bezt->f1 |= 1;
|
|
bezt->f2 |= 1;
|
|
bezt->f3 |= 1;
|
|
}
|
|
}
|
|
bezt++;
|
|
}
|
|
}
|
|
else if(bp) {
|
|
a= nu->pntsu*nu->pntsv;
|
|
bp= nu->bp;
|
|
while(a--) {
|
|
if(bp->hide==0) {
|
|
if(G.qual & LR_SHIFTKEY) {
|
|
bp->f1 &= ~1;
|
|
}
|
|
else {
|
|
bp->f1 |= 1;
|
|
}
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
|
|
countall();
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
|
|
void selectrow_nurb()
|
|
{
|
|
static BPoint *last=0;
|
|
static int direction=0;
|
|
Nurb *nu;
|
|
BPoint *bp;
|
|
int u = 0, v = 0, a, b, ok=0;
|
|
|
|
if(editNurb.first==0) return;
|
|
if(G.obedit==0 || G.obedit->type!=OB_SURF) return;
|
|
if(lastselbp==0) return;
|
|
|
|
/* zoek de juiste nurb en toggle met u of v */
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
bp= nu->bp;
|
|
for(v=0; v<nu->pntsv; v++) {
|
|
for(u=0; u<nu->pntsu; u++, bp++) {
|
|
if(bp==lastselbp) {
|
|
if(bp->f1 & 1) {
|
|
ok= 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(ok) break;
|
|
}
|
|
if(ok) {
|
|
if(last==lastselbp) {
|
|
direction= 1-direction;
|
|
setflagsNurb(0);
|
|
}
|
|
last= lastselbp;
|
|
|
|
bp= nu->bp;
|
|
for(a=0; a<nu->pntsv; a++) {
|
|
for(b=0; b<nu->pntsu; b++, bp++) {
|
|
if(direction) {
|
|
if(a==v) if(bp->hide==0) bp->f1 |= 1;
|
|
}
|
|
else {
|
|
if(b==u) if(bp->hide==0) bp->f1 |= 1;
|
|
}
|
|
}
|
|
}
|
|
countall();
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
return;
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
}
|
|
|
|
void adduplicate_nurb()
|
|
{
|
|
|
|
if( (G.vd->lay & G.obedit->lay)==0 ) return;
|
|
|
|
adduplicateflagNurb(1);
|
|
|
|
countall();
|
|
transform('d');
|
|
}
|
|
|
|
void delNurb()
|
|
{
|
|
Nurb *nu, *next, *nu1;
|
|
BezTriple *bezt, *bezt1, *bezt2;
|
|
BPoint *bp, *bp1, *bp2;
|
|
int a;
|
|
short event, cut = 0;
|
|
|
|
if(G.obedit==0 ) return;
|
|
if( (G.vd->lay & G.obedit->lay)==0 ) return;
|
|
|
|
if(G.obedit->type==OB_SURF) event= pupmenu("ERASE %t|Selected%x0|All%x2");
|
|
else event= pupmenu("ERASE %t|Selected%x0|Segment%x1|All%x2");
|
|
|
|
if(event== -1) return;
|
|
|
|
if(G.obedit->type==OB_SURF) {
|
|
if(event==0) deleteflagNurb(1);
|
|
else freeNurblist(&editNurb);
|
|
|
|
countall();
|
|
makeDispList(G.obedit);
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
return;
|
|
}
|
|
|
|
if(event==0) {
|
|
/* eerste doorloop, kunnen hele stukken weg? */
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
next= nu->next;
|
|
if( (nu->type & 7)==CU_BEZIER ) {
|
|
bezt= nu->bezt;
|
|
a= nu->pntsu;
|
|
if(a) {
|
|
while(a) {
|
|
if( BEZSELECTED(bezt) );
|
|
else break;
|
|
a--;
|
|
bezt++;
|
|
}
|
|
if(a==0) {
|
|
BLI_remlink(&editNurb, nu);
|
|
freeNurb(nu);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
bp= nu->bp;
|
|
a= nu->pntsu*nu->pntsv;
|
|
if(a) {
|
|
while(a) {
|
|
if(bp->f1 & 1 );
|
|
else break;
|
|
a--;
|
|
bp++;
|
|
}
|
|
if(a==0) {
|
|
BLI_remlink(&editNurb, nu);
|
|
freeNurb(nu);
|
|
}
|
|
}
|
|
}
|
|
nu= next;
|
|
}
|
|
/* tweede doorloop, kleine stukken weg: alleen curves */
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
next= nu->next;
|
|
event= 0;
|
|
if( (nu->type & 7)==CU_BEZIER ) {
|
|
bezt= nu->bezt;
|
|
for(a=0;a<nu->pntsu;a++) {
|
|
if( BEZSELECTED(bezt) ) {
|
|
memcpy(bezt, bezt+1, (nu->pntsu-a-1)*sizeof(BezTriple));
|
|
nu->pntsu--;
|
|
a--;
|
|
event= 1;
|
|
}
|
|
else bezt++;
|
|
}
|
|
if(event) {
|
|
bezt1 =
|
|
(BezTriple*)MEM_mallocN((nu->pntsu) * sizeof(BezTriple), "delNurb");
|
|
memcpy(bezt1, nu->bezt, (nu->pntsu)*sizeof(BezTriple) );
|
|
MEM_freeN(nu->bezt);
|
|
nu->bezt= bezt1;
|
|
calchandlesNurb(nu);
|
|
}
|
|
}
|
|
else if(nu->pntsv==1) {
|
|
bp= nu->bp;
|
|
|
|
for(a=0;a<nu->pntsu;a++) {
|
|
if( bp->f1 & 1 ) {
|
|
memcpy(bp, bp+1, (nu->pntsu-a-1)*sizeof(BPoint));
|
|
nu->pntsu--;
|
|
a--;
|
|
event= 1;
|
|
}
|
|
else {
|
|
bp++;
|
|
}
|
|
}
|
|
if(event) {
|
|
bp1 = (BPoint*)MEM_mallocN(nu->pntsu * sizeof(BPoint), "delNurb2");
|
|
memcpy(bp1, nu->bp, (nu->pntsu)*sizeof(BPoint) );
|
|
MEM_freeN(nu->bp);
|
|
nu->bp= bp1;
|
|
}
|
|
makeknots(nu, 1, nu->flagu>>1);
|
|
}
|
|
nu= next;
|
|
}
|
|
}
|
|
else if(event==1) { /* erase segment */
|
|
/* vind de twee geselecteerde punten */
|
|
bezt1= bezt2= 0;
|
|
bp1= bp2= 0;
|
|
nu= editNurb.first;
|
|
nu1= 0;
|
|
while(nu) {
|
|
next= nu->next;
|
|
if( (nu->type & 7)==CU_BEZIER ) {
|
|
bezt= nu->bezt;
|
|
for(a=0; a<nu->pntsu-1; a++) {
|
|
if( BEZSELECTED(bezt) ) {
|
|
bezt1= bezt;
|
|
bezt2= bezt+1;
|
|
if( (bezt2->f1 & 1) || (bezt2->f2 & 1) || (bezt2->f3 & 1) ) ;
|
|
else { /* misschien niet cyclic maken */
|
|
if(a==0 && (nu->flagu & 1) ) {
|
|
bezt2= bezt+(nu->pntsu-1);
|
|
if( (bezt2->f1 & 1) || (bezt2->f2 & 1) || (bezt2->f3 & 1) ) {
|
|
nu->flagu--;
|
|
makeDispList(G.obedit);
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
cut= a;
|
|
nu1= nu;
|
|
break;
|
|
}
|
|
bezt++;
|
|
}
|
|
}
|
|
else if(nu->pntsv==1) {
|
|
bp= nu->bp;
|
|
for(a=0; a<nu->pntsu-1; a++) {
|
|
if( bp->f1 & 1 ) {
|
|
bp1= bp;
|
|
bp2= bp+1;
|
|
if( bp2->f1 & 1 ) ;
|
|
else { /* misschien niet cyclic maken */
|
|
if(a==0 && (nu->flagu & 1) ) {
|
|
bp2= bp+(nu->pntsu-1);
|
|
if( bp2->f1 & 1 ) {
|
|
nu->flagu--;
|
|
makeDispList(G.obedit);
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
cut= a;
|
|
nu1= nu;
|
|
break;
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
if(nu1) break;
|
|
|
|
nu= nu->next;
|
|
}
|
|
if(nu1) {
|
|
if(bezt1) {
|
|
if(nu1->pntsu==2) { /* helemaal weg */
|
|
BLI_remlink(&editNurb, nu);
|
|
freeNurb(nu);
|
|
}
|
|
else if(nu1->flagu & 1) { /* cyclic */
|
|
bezt =
|
|
(BezTriple*)MEM_mallocN((cut+1) * sizeof(BezTriple), "delNurb1");
|
|
memcpy(bezt, nu1->bezt,(cut+1)*sizeof(BezTriple));
|
|
a= nu1->pntsu-cut-1;
|
|
memcpy(nu1->bezt, bezt2, a*sizeof(BezTriple));
|
|
memcpy(nu1->bezt+a, bezt, (cut+1)*sizeof(BezTriple));
|
|
nu1->flagu--;
|
|
MEM_freeN(bezt);
|
|
calchandlesNurb(nu);
|
|
}
|
|
else { /* nieuwe curve erbij */
|
|
|
|
/* hier zit een fout in... maar waar? (a kan nul worden) */
|
|
|
|
nu =
|
|
(Nurb*)MEM_mallocN(sizeof(Nurb), "delNurb2");
|
|
memcpy(nu, nu1, sizeof(Nurb));
|
|
BLI_addtail(&editNurb, nu);
|
|
nu->bezt =
|
|
(BezTriple*)MEM_mallocN((cut+1) * sizeof(BezTriple), "delNurb3");
|
|
memcpy(nu->bezt, nu1->bezt,(cut+1)*sizeof(BezTriple));
|
|
a= nu1->pntsu-cut-1;
|
|
|
|
bezt =
|
|
(BezTriple*)MEM_mallocN(a * sizeof(BezTriple), "delNurb4");
|
|
memcpy(bezt, nu1->bezt+cut+1,a*sizeof(BezTriple));
|
|
MEM_freeN(nu1->bezt);
|
|
nu1->bezt= bezt;
|
|
nu1->pntsu= a;
|
|
nu->pntsu= cut+1;
|
|
|
|
|
|
calchandlesNurb(nu);
|
|
calchandlesNurb(nu1);
|
|
}
|
|
}
|
|
else if(bp1) {
|
|
if(nu1->pntsu==2) { /* helemaal weg */
|
|
BLI_remlink(&editNurb, nu);
|
|
freeNurb(nu);
|
|
}
|
|
else if(nu1->flagu & 1) { /* cyclic */
|
|
bp =
|
|
(BPoint*)MEM_mallocN((cut+1) * sizeof(BPoint), "delNurb5");
|
|
memcpy(bp, nu1->bp,(cut+1)*sizeof(BPoint));
|
|
a= nu1->pntsu-cut-1;
|
|
memcpy(nu1->bp, bp2, a*sizeof(BPoint));
|
|
memcpy(nu1->bp+a, bp, (cut+1)*sizeof(BPoint));
|
|
nu1->flagu--;
|
|
MEM_freeN(bp);
|
|
}
|
|
else { /* nieuwe curve erbij */
|
|
nu = (Nurb*)MEM_mallocN(sizeof(Nurb), "delNurb6");
|
|
memcpy(nu, nu1, sizeof(Nurb));
|
|
BLI_addtail(&editNurb, nu);
|
|
nu->bp =
|
|
(BPoint*)MEM_mallocN((cut+1) * sizeof(BPoint), "delNurb7");
|
|
memcpy(nu->bp, nu1->bp,(cut+1)*sizeof(BPoint));
|
|
a= nu1->pntsu-cut-1;
|
|
bp =
|
|
(BPoint*)MEM_mallocN(a * sizeof(BPoint), "delNurb8");
|
|
memcpy(bp, nu1->bp+cut+1,a*sizeof(BPoint));
|
|
MEM_freeN(nu1->bp);
|
|
nu1->bp= bp;
|
|
nu1->pntsu= a;
|
|
nu->pntsu= cut+1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(event==2) {
|
|
freeNurblist(&editNurb);
|
|
}
|
|
|
|
countall();
|
|
makeDispList(G.obedit);
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
|
|
|
|
void join_curve(int type)
|
|
{
|
|
Base *base, *nextb;
|
|
Object *ob;
|
|
Curve *cu;
|
|
Nurb *nu, *newnu;
|
|
BezTriple *bezt;
|
|
BPoint *bp;
|
|
ListBase tempbase;
|
|
float imat[4][4], cmat[4][4];
|
|
int a;
|
|
|
|
if(G.obedit) return;
|
|
|
|
ob= OBACT;
|
|
if(ob->type!=type) return;
|
|
if(ob->lay & G.vd->lay); else return;
|
|
tempbase.first= tempbase.last= 0;
|
|
|
|
if(type==OB_SURF) {
|
|
if(okee("Join selected Nurbs")==0) return;
|
|
}
|
|
else if(okee("Join selected Curves")==0) return;
|
|
|
|
/* alle geselecteerde curves invers transformen in obact */
|
|
Mat4Invert(imat, ob->obmat);
|
|
|
|
base= FIRSTBASE;
|
|
while(base) {
|
|
nextb= base->next;
|
|
if TESTBASE(base) {
|
|
if(base->object->type==type) {
|
|
if(base->object != ob) {
|
|
|
|
cu= base->object->data;
|
|
|
|
if(cu->nurb.first) {
|
|
/* let op: matmul omkeren is ECHT fout */
|
|
Mat4MulMat4(cmat, base->object->obmat, imat);
|
|
|
|
nu= cu->nurb.first;
|
|
while(nu) {
|
|
newnu= duplicateNurb(nu);
|
|
BLI_addtail(&tempbase, newnu);
|
|
|
|
if( (bezt= newnu->bezt) ) {
|
|
a= newnu->pntsu;
|
|
while(a--) {
|
|
Mat4MulVecfl(cmat, bezt->vec[0]);
|
|
Mat4MulVecfl(cmat, bezt->vec[1]);
|
|
Mat4MulVecfl(cmat, bezt->vec[2]);
|
|
bezt++;
|
|
}
|
|
}
|
|
if( (bp= newnu->bp) ) {
|
|
a= newnu->pntsu*nu->pntsv;
|
|
while(a--) {
|
|
Mat4MulVecfl(cmat, bp->vec);
|
|
bp++;
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
}
|
|
|
|
free_and_unlink_base(base);
|
|
}
|
|
}
|
|
}
|
|
base= nextb;
|
|
}
|
|
|
|
cu= ob->data;
|
|
addlisttolist(&cu->nurb, &tempbase);
|
|
|
|
enter_editmode();
|
|
exit_editmode(1);
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
|
|
|
|
|
|
Nurb *addNurbprim(int type, int stype, int newname)
|
|
/* type: &8= 2D; 0=poly,1 bez, 4 nurb
|
|
* stype: 0: 2/4 punts curve
|
|
* 1: 8 punts cirkel
|
|
* 2: 4x4 patch Nurb
|
|
* 3: tube 4:sphere 5:donut
|
|
* 6: 5 punts, 5e order rechte lijn (pad) alleen nurbspline!
|
|
*/
|
|
{
|
|
static int xzproj= 0;
|
|
Nurb *nu = NULL;
|
|
BezTriple *bezt;
|
|
BPoint *bp;
|
|
float *curs, cent[3],vec[3],imat[3][3],mat[3][3];
|
|
float fac,cmat[3][3];
|
|
int a, b;
|
|
|
|
/* imat en centrum en afmeting */
|
|
if(G.obedit) {
|
|
|
|
Mat3CpyMat4(mat, G.obedit->obmat);
|
|
curs= give_cursor();
|
|
VECCOPY(cent, curs);
|
|
cent[0]-= G.obedit->obmat[3][0];
|
|
cent[1]-= G.obedit->obmat[3][1];
|
|
cent[2]-= G.obedit->obmat[3][2];
|
|
|
|
Mat3CpyMat4(imat, G.vd->viewmat);
|
|
Mat3MulVecfl(imat, cent);
|
|
Mat3MulMat3(cmat, imat, mat);
|
|
Mat3Inv(imat, cmat);
|
|
setflagsNurb(0);
|
|
}
|
|
else {
|
|
Mat3One(imat);
|
|
cent[0]= cent[1]= cent[2]= 0.0;
|
|
}
|
|
|
|
if ELEM5(stype, 0, 1, 2, 4, 6) {
|
|
nu = (Nurb*)MEM_callocN(sizeof(Nurb), "addNurbprim");
|
|
nu->type= type;
|
|
nu->resolu= 12;
|
|
nu->resolv= 12;
|
|
/* if(G.obedit && (G.mainb==5 || G.mainb==9)) nu->col= 0; */
|
|
}
|
|
|
|
switch(stype) {
|
|
case 0: /* curve */
|
|
if(newname) {
|
|
rename_id((ID *)G.obedit, "Curve");
|
|
rename_id((ID *)G.obedit->data, "Curve");
|
|
}
|
|
if((type & 7)==CU_BEZIER) {
|
|
nu->pntsu= 2;
|
|
nu->bezt =
|
|
(BezTriple*)MEM_callocN(2 * sizeof(BezTriple), "addNurbprim1");
|
|
bezt= nu->bezt;
|
|
bezt->h1= bezt->h2= HD_ALIGN;
|
|
bezt->f1= bezt->f2= bezt->f3= 1;
|
|
|
|
for(a=0;a<3;a++) {
|
|
VECCOPY(bezt->vec[a], cent);
|
|
}
|
|
bezt->vec[1][0]+= -G.vd->grid;
|
|
bezt->vec[0][0]+= -1.5*G.vd->grid;
|
|
bezt->vec[0][1]+= -0.5*G.vd->grid;
|
|
bezt->vec[2][0]+= -0.5*G.vd->grid;
|
|
bezt->vec[2][1]+= 0.5*G.vd->grid;
|
|
for(a=0;a<3;a++) Mat3MulVecfl(imat, bezt->vec[a]);
|
|
|
|
bezt++;
|
|
bezt->h1= bezt->h2= HD_ALIGN;
|
|
bezt->f1= bezt->f2= bezt->f3= 1;
|
|
|
|
for(a=0;a<3;a++) {
|
|
VECCOPY(bezt->vec[a], cent);
|
|
}
|
|
bezt->vec[1][0]+= G.vd->grid;
|
|
for(a=0;a<3;a++) Mat3MulVecfl(imat, bezt->vec[a]);
|
|
|
|
calchandlesNurb(nu);
|
|
}
|
|
else {
|
|
nu->pntsu= 4;
|
|
nu->pntsv= 1;
|
|
nu->orderu= 4;
|
|
nu->bp= callocstructN(BPoint, 4, "addNurbprim3");
|
|
|
|
bp= nu->bp;
|
|
for(a=0;a<4;a++, bp++) {
|
|
VECCOPY(bp->vec, cent);
|
|
bp->vec[3]= 1.0;
|
|
bp->f1= 1;
|
|
}
|
|
|
|
bp= nu->bp;
|
|
bp->vec[0]+= -1.5*G.vd->grid;
|
|
bp++;
|
|
bp->vec[0]+= -G.vd->grid;
|
|
bp->vec[1]+= G.vd->grid;
|
|
bp++;
|
|
bp->vec[0]+= G.vd->grid;
|
|
bp->vec[1]+= G.vd->grid;
|
|
bp++;
|
|
bp->vec[0]+= 1.5*G.vd->grid;
|
|
|
|
bp= nu->bp;
|
|
for(a=0;a<4;a++, bp++) Mat3MulVecfl(imat,bp->vec);
|
|
|
|
if((type & 7)==4) {
|
|
nu->knotsu= 0; /* makeknots alloceert */
|
|
makeknots(nu, 1, nu->flagu>>1);
|
|
}
|
|
|
|
}
|
|
break;
|
|
case 6: /* 5 punts pad */
|
|
nu->pntsu= 5;
|
|
nu->pntsv= 1;
|
|
nu->orderu= 5;
|
|
nu->flagu= 2; /* endpoint */
|
|
nu->resolu= 32;
|
|
nu->bp= callocstructN(BPoint, 5, "addNurbprim3");
|
|
|
|
bp= nu->bp;
|
|
for(a=0;a<5;a++, bp++) {
|
|
VECCOPY(bp->vec, cent);
|
|
bp->vec[3]= 1.0;
|
|
bp->f1= 1;
|
|
}
|
|
|
|
bp= nu->bp;
|
|
bp->vec[0]+= -2.0*G.vd->grid;
|
|
bp++;
|
|
bp->vec[0]+= -G.vd->grid;
|
|
bp++; bp++;
|
|
bp->vec[0]+= G.vd->grid;
|
|
bp++;
|
|
bp->vec[0]+= 2.0*G.vd->grid;
|
|
|
|
bp= nu->bp;
|
|
for(a=0;a<5;a++, bp++) Mat3MulVecfl(imat,bp->vec);
|
|
|
|
if((type & 7)==4) {
|
|
nu->knotsu= 0; /* makeknots alloceert */
|
|
makeknots(nu, 1, nu->flagu>>1);
|
|
}
|
|
|
|
break;
|
|
case 1: /* cirkel */
|
|
if(newname) {
|
|
rename_id((ID *)G.obedit, "CurveCircle");
|
|
rename_id((ID *)G.obedit->data, "CurveCircle");
|
|
}
|
|
if((type & 7)==CU_BEZIER) {
|
|
nu->pntsu= 4;
|
|
nu->bezt= callocstructN(BezTriple, 4, "addNurbprim1");
|
|
nu->flagu= 1;
|
|
bezt= nu->bezt;
|
|
|
|
for(a=0;a<3;a++) {
|
|
VECCOPY(bezt->vec[a], cent);
|
|
}
|
|
bezt->h1= bezt->h2= HD_AUTO;
|
|
bezt->f1= bezt->f2= bezt->f3= 1;
|
|
bezt->vec[1][0]+= -G.vd->grid;
|
|
for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
|
|
|
|
bezt++;
|
|
for(a=0;a<3;a++) {
|
|
VECCOPY(bezt->vec[a], cent);
|
|
}
|
|
bezt->h1= bezt->h2= HD_AUTO;
|
|
bezt->f1= bezt->f2= bezt->f3= 1;
|
|
bezt->vec[1][1]+= G.vd->grid;
|
|
for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
|
|
|
|
bezt++;
|
|
for(a=0;a<3;a++) {
|
|
VECCOPY(bezt->vec[a], cent);
|
|
}
|
|
bezt->h1= bezt->h2= HD_AUTO;
|
|
bezt->f1= bezt->f2= bezt->f3= 1;
|
|
bezt->vec[1][0]+= G.vd->grid;
|
|
for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
|
|
|
|
bezt++;
|
|
for(a=0;a<3;a++) {
|
|
VECCOPY(bezt->vec[a], cent);
|
|
}
|
|
bezt->h1= bezt->h2= HD_AUTO;
|
|
bezt->f1= bezt->f2= bezt->f3= 1;
|
|
bezt->vec[1][1]+= -G.vd->grid;
|
|
for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
|
|
|
|
calchandlesNurb(nu);
|
|
}
|
|
else if( (type & 7)==CU_NURBS ) { /* nurb */
|
|
nu->pntsu= 8;
|
|
nu->pntsv= 1;
|
|
nu->orderu= 4;
|
|
nu->bp= callocstructN(BPoint, 8, "addNurbprim6");
|
|
nu->flagu= 1;
|
|
bp= nu->bp;
|
|
|
|
for(a=0; a<8; a++) {
|
|
bp->f1= 1;
|
|
VECCOPY(bp->vec, cent);
|
|
|
|
if(xzproj==0) {
|
|
bp->vec[0]+= nurbcircle[a][0]*G.vd->grid;
|
|
bp->vec[1]+= nurbcircle[a][1]*G.vd->grid;
|
|
}
|
|
else {
|
|
bp->vec[0]+= 0.25*nurbcircle[a][0]*G.vd->grid-.75*G.vd->grid;
|
|
bp->vec[2]+= 0.25*nurbcircle[a][1]*G.vd->grid;
|
|
}
|
|
if(a & 1) bp->vec[3]= 0.25*sqrt(2.0);
|
|
else bp->vec[3]= 1.0;
|
|
Mat3MulVecfl(imat,bp->vec);
|
|
bp++;
|
|
}
|
|
|
|
makeknots(nu, 1, nu->flagu>>1);
|
|
}
|
|
break;
|
|
case 2: /* 4x4 patch */
|
|
if( (type & 7)==CU_NURBS ) { /* nurb */
|
|
if(newname) {
|
|
rename_id((ID *)G.obedit, "Surf");
|
|
rename_id((ID *)G.obedit->data, "Surf");
|
|
}
|
|
|
|
nu->pntsu= 4;
|
|
nu->pntsv= 4;
|
|
nu->orderu= 4;
|
|
nu->orderv= 4;
|
|
nu->flag= ME_SMOOTH;
|
|
nu->bp= callocstructN(BPoint, 4*4, "addNurbprim6");
|
|
nu->flagu= 0;
|
|
nu->flagv= 0;
|
|
bp= nu->bp;
|
|
|
|
for(a=0; a<4; a++) {
|
|
for(b=0; b<4; b++) {
|
|
VECCOPY(bp->vec, cent);
|
|
bp->f1= 1;
|
|
fac= (float)a -1.5;
|
|
bp->vec[0]+= fac*G.vd->grid;
|
|
fac= (float)b -1.5;
|
|
bp->vec[1]+= fac*G.vd->grid;
|
|
if(a==1 || a==2) if(b==1 || b==2) {
|
|
bp->vec[2]+= G.vd->grid;
|
|
}
|
|
Mat3MulVecfl(imat,bp->vec);
|
|
bp->vec[3]= 1.0;
|
|
bp++;
|
|
}
|
|
}
|
|
|
|
makeknots(nu, 1, nu->flagu>>1);
|
|
makeknots(nu, 2, nu->flagv>>1);
|
|
}
|
|
break;
|
|
case 3: /* tube */
|
|
if( (type & 7)==CU_NURBS ) {
|
|
if(newname) {
|
|
rename_id((ID *)G.obedit, "SurfTube");
|
|
rename_id((ID *)G.obedit->data, "SurfTube");
|
|
}
|
|
|
|
nu= addNurbprim(4, 1, 0); /* cirkel */
|
|
nu->resolu= 32;
|
|
nu->flag= ME_SMOOTH;
|
|
BLI_addtail(&editNurb, nu); /* tijdelijk voor extrude en translate */
|
|
vec[0]=vec[1]= 0.0;
|
|
vec[2]= -G.vd->grid;
|
|
Mat3MulVecfl(imat, vec);
|
|
translateflagNurb(1, vec);
|
|
extrudeflagNurb(1);
|
|
vec[0]= -2*vec[0];
|
|
vec[1]= -2*vec[1];
|
|
vec[2]= -2*vec[2];
|
|
translateflagNurb(1, vec);
|
|
|
|
BLI_remlink(&editNurb, nu);
|
|
|
|
a= nu->pntsu*nu->pntsv;
|
|
bp= nu->bp;
|
|
while(a-- >0) {
|
|
bp->f1 |= 1;
|
|
bp++;
|
|
}
|
|
}
|
|
break;
|
|
case 4: /* sphere */
|
|
if( (type & 7)==CU_NURBS ) {
|
|
if(newname) {
|
|
rename_id((ID *)G.obedit, "SurfSphere");
|
|
rename_id((ID *)G.obedit->data, "SurfSphere");
|
|
}
|
|
|
|
nu->pntsu= 5;
|
|
nu->pntsv= 1;
|
|
nu->orderu= 3;
|
|
nu->resolu= 24;
|
|
nu->resolv= 32;
|
|
nu->flag= ME_SMOOTH;
|
|
nu->bp= callocstructN(BPoint, 5, "addNurbprim6");
|
|
nu->flagu= 0;
|
|
bp= nu->bp;
|
|
|
|
for(a=0; a<5; a++) {
|
|
bp->f1= 1;
|
|
VECCOPY(bp->vec, cent);
|
|
bp->vec[0]+= nurbcircle[a][0]*G.vd->grid;
|
|
bp->vec[2]+= nurbcircle[a][1]*G.vd->grid;
|
|
if(a & 1) bp->vec[3]= 0.5*sqrt(2.0);
|
|
else bp->vec[3]= 1.0;
|
|
Mat3MulVecfl(imat,bp->vec);
|
|
bp++;
|
|
}
|
|
nu->flagu= 4;
|
|
makeknots(nu, 1, nu->flagu>>1);
|
|
|
|
BLI_addtail(&editNurb, nu); /* tijdelijk voor spin */
|
|
spinNurb(0, 0);
|
|
|
|
makeknots(nu, 2, nu->flagv>>1);
|
|
|
|
a= nu->pntsu*nu->pntsv;
|
|
bp= nu->bp;
|
|
while(a-- >0) {
|
|
bp->f1 |= 1;
|
|
bp++;
|
|
}
|
|
BLI_remlink(&editNurb, nu);
|
|
}
|
|
break;
|
|
case 5: /* donut */
|
|
if( (type & 7)==CU_NURBS ) {
|
|
if(newname) {
|
|
rename_id((ID *)G.obedit, "SurfDonut");
|
|
rename_id((ID *)G.obedit->data, "SurfDonut");
|
|
}
|
|
|
|
xzproj= 1;
|
|
nu= addNurbprim(4, 1, 0); /* cirkel */
|
|
xzproj= 0;
|
|
nu->resolu= 24;
|
|
nu->resolv= 32;
|
|
nu->flag= ME_SMOOTH;
|
|
BLI_addtail(&editNurb, nu); /* tijdelijk voor extrude en translate */
|
|
spinNurb(0, 0);
|
|
|
|
BLI_remlink(&editNurb, nu);
|
|
|
|
a= nu->pntsu*nu->pntsv;
|
|
bp= nu->bp;
|
|
while(a-- >0) {
|
|
bp->f1 |= 1;
|
|
bp++;
|
|
}
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* altijd doen: */
|
|
nu->flag= ME_SMOOTH;
|
|
|
|
test2DNurb(nu);
|
|
|
|
return nu;
|
|
}
|
|
|
|
void default_curve_ipo(Curve *cu)
|
|
{
|
|
IpoCurve *icu;
|
|
BezTriple *bezt;
|
|
|
|
if(cu->ipo) return;
|
|
|
|
cu->ipo= add_ipo("CurveIpo", ID_CU);
|
|
|
|
icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
|
|
|
|
icu->blocktype= ID_CU;
|
|
icu->adrcode= CU_SPEED;
|
|
icu->flag= IPO_VISIBLE+IPO_SELECT;
|
|
set_icu_vars(icu);
|
|
|
|
BLI_addtail( &(cu->ipo->curve), icu);
|
|
|
|
icu->bezt= bezt= MEM_callocN(2*sizeof(BezTriple), "defaultipo");
|
|
icu->totvert= 2;
|
|
|
|
bezt->hide= IPO_BEZ;
|
|
bezt->f1=bezt->f2= bezt->f3= SELECT;
|
|
bezt->h1= bezt->h2= HD_AUTO;
|
|
bezt++;
|
|
bezt->vec[1][0]= 100.0;
|
|
bezt->vec[1][1]= 1.0;
|
|
bezt->hide= IPO_BEZ;
|
|
bezt->f1=bezt->f2= bezt->f3= SELECT;
|
|
bezt->h1= bezt->h2= HD_AUTO;
|
|
|
|
calchandles_ipocurve(icu);
|
|
}
|
|
|
|
void add_primitiveCurve(int stype)
|
|
{
|
|
Nurb *nu;
|
|
Curve *cu;
|
|
int type, newname= 0;
|
|
|
|
if(G.scene->id.lib) return;
|
|
|
|
/* this function also comes from an info window */
|
|
if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return;
|
|
if(G.vd==0) return;
|
|
|
|
if(stype>=10 && stype<20) type= CU_2D+1;
|
|
else if(stype>=20 && stype<30) type= CU_2D+2;
|
|
else if(stype>=30 && stype<40) type= CU_2D+3;
|
|
else if(stype>=40 && stype<50) {
|
|
if(stype==46) type= 4;
|
|
else type= CU_2D+4;
|
|
}
|
|
else type= CU_2D;
|
|
|
|
check_editmode(OB_CURVE);
|
|
|
|
/* als geen obedit: nieuw object en in editmode gaan */
|
|
if(G.obedit==0) {
|
|
add_object(OB_CURVE);
|
|
base_init_from_view3d(BASACT, G.vd);
|
|
G.obedit= BASACT->object;
|
|
|
|
where_is_object(G.obedit);
|
|
|
|
make_editNurb();
|
|
setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
|
|
newname= 1;
|
|
|
|
cu= G.obedit->data;
|
|
if(stype==46) {
|
|
cu->flag |= (CU_3D+CU_PATH);
|
|
|
|
default_curve_ipo(cu);
|
|
}
|
|
}
|
|
else cu= G.obedit->data;
|
|
|
|
if(cu->flag & CU_3D) type &= ~CU_2D;
|
|
|
|
stype= (stype % 10);
|
|
|
|
nu= addNurbprim(type, stype, newname); /* 2D */
|
|
|
|
BLI_addtail(&editNurb, nu);
|
|
makeDispList(G.obedit);
|
|
|
|
allqueue(REDRAWBUTSEDIT, 0);
|
|
|
|
countall();
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
|
|
void add_primitiveNurb(int type)
|
|
{
|
|
Nurb *nu;
|
|
int newname= 0;
|
|
|
|
if(G.scene->id.lib) return;
|
|
if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return;
|
|
|
|
check_editmode(OB_SURF);
|
|
|
|
/* als geen obedit: nieuw object en in editmode gaan */
|
|
if(G.obedit==0) {
|
|
add_object(OB_SURF);
|
|
base_init_from_view3d(BASACT, G.vd);
|
|
G.obedit= BASACT->object;
|
|
|
|
where_is_object(G.obedit);
|
|
|
|
make_editNurb();
|
|
setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
|
|
newname= 1;
|
|
}
|
|
|
|
nu= addNurbprim(4, type, newname);
|
|
BLI_addtail(&editNurb,nu);
|
|
makeDispList(G.obedit);
|
|
|
|
allqueue(REDRAWBUTSEDIT, 0);
|
|
|
|
countall();
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
|
|
|
|
|
|
void clear_tilt()
|
|
{
|
|
Nurb *nu;
|
|
BezTriple *bezt;
|
|
BPoint *bp;
|
|
int a;
|
|
|
|
if(okee("Clear tilt")==0) return;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if( nu->bezt ) {
|
|
bezt= nu->bezt;
|
|
a= nu->pntsu;
|
|
while(a--) {
|
|
if(BEZSELECTED(bezt)) bezt->alfa= 0.0;
|
|
bezt++;
|
|
}
|
|
}
|
|
else if(nu->bp) {
|
|
bp= nu->bp;
|
|
a= nu->pntsu*nu->pntsv;
|
|
while(a--) {
|
|
if(bp->f1 & 1) bp->alfa= 0.0;
|
|
bp++;
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
|
|
makeBevelList(G.obedit);
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
|
|
void clever_numbuts_curve()
|
|
{
|
|
BPoint *bp;
|
|
BezTriple *bezt;
|
|
float old[3], delta[3];
|
|
int a;
|
|
|
|
if(lastnu==0) return;
|
|
if(lastnu->bp) {
|
|
bp= lastnu->bp;
|
|
a= lastnu->pntsu*lastnu->pntsv;
|
|
while(a--) {
|
|
if(bp->f1 & 1) break;
|
|
bp++;
|
|
}
|
|
if(bp==0) return;
|
|
|
|
add_numbut(0, NUM|FLO, "LocX:", -G.vd->far, G.vd->far, bp->vec, 0);
|
|
add_numbut(1, NUM|FLO, "LocY:", -G.vd->far, G.vd->far, bp->vec+1, 0);
|
|
add_numbut(2, NUM|FLO, "LocZ:", -G.vd->far, G.vd->far, bp->vec+2, 0);
|
|
add_numbut(3, NUM|FLO, " W:", 0.0, 100.0, bp->vec+3, 0);
|
|
|
|
do_clever_numbuts("Active BPoint", 4, REDRAW);
|
|
makeDispList(G.obedit);
|
|
}
|
|
else if(lastnu->bezt) {
|
|
bezt= lastnu->bezt;
|
|
a= lastnu->pntsu;
|
|
while(a--) {
|
|
if(BEZSELECTED(bezt)) break;
|
|
bezt++;
|
|
}
|
|
if(bezt==0) return;
|
|
|
|
if(bezt->f2 & 1) {
|
|
add_numbut(0, NUM|FLO, "LocX:", -G.vd->far, G.vd->far, bezt->vec[1], 0);
|
|
add_numbut(1, NUM|FLO, "LocY:", -G.vd->far, G.vd->far, bezt->vec[1]+1, 0);
|
|
add_numbut(2, NUM|FLO, "LocZ:", -G.vd->far, G.vd->far, bezt->vec[1]+2, 0);
|
|
VECCOPY(old, bezt->vec[1]);
|
|
do_clever_numbuts("Active BezierPoint", 3, REDRAW);
|
|
|
|
VecSubf(delta, bezt->vec[1], old);
|
|
VecAddf(bezt->vec[0], bezt->vec[0], delta);
|
|
VecAddf(bezt->vec[2], bezt->vec[2], delta);
|
|
makeDispList(G.obedit);
|
|
}
|
|
else if(bezt->f1 & 1) {
|
|
add_numbut(0, NUM|FLO, "LocX:", -G.vd->far, G.vd->far, bezt->vec[0], 0);
|
|
add_numbut(1, NUM|FLO, "LocY:", -G.vd->far, G.vd->far, bezt->vec[0]+1, 0);
|
|
add_numbut(2, NUM|FLO, "LocZ:", -G.vd->far, G.vd->far, bezt->vec[0]+2, 0);
|
|
|
|
do_clever_numbuts("Active HandlePoint", 3, REDRAW);
|
|
}
|
|
else if(bezt->f3 & 1) {
|
|
add_numbut(0, NUM|FLO, "LocX:", -G.vd->far, G.vd->far, bezt->vec[0], 0);
|
|
add_numbut(1, NUM|FLO, "LocY:", -G.vd->far, G.vd->far, bezt->vec[2]+1, 0);
|
|
add_numbut(2, NUM|FLO, "LocZ:", -G.vd->far, G.vd->far, bezt->vec[2]+2, 0);
|
|
|
|
do_clever_numbuts("Active HandlePoint", 3, REDRAW);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
int bezt_compare (const void *e1, const void *e2)
|
|
{
|
|
BezTriple *b1 = *((BezTriple**)e1);
|
|
BezTriple *b2 = *((BezTriple**)e2);
|
|
|
|
/* Check numerical values */
|
|
float val = b1->vec[1][0] - b2->vec[1][0];
|
|
|
|
if (val<0)
|
|
return -1;
|
|
|
|
if (val>0)
|
|
return 1;
|
|
|
|
/* Check selected flags : Ensures that selected keys will be listed first */
|
|
|
|
if ((b1->f2 & 1) && !(b2->f2 & 1))
|
|
return -1;
|
|
if (!(b1->f2 & 1) && (b2->f2 & 1))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|