diff options
Diffstat (limited to 'release')
28 files changed, 4309 insertions, 202 deletions
diff --git a/release/scripts/UVpaint05.py b/release/scripts/UVpaint05.py new file mode 100644 index 00000000000..b994be23871 --- /dev/null +++ b/release/scripts/UVpaint05.py @@ -0,0 +1,442 @@ +#!BPY +""" Registration info for Blender menus: <- these words are ignored +Name: 'UVpainter' +Blender: 232 +Group: 'UV' +Tip: 'Use vertex paint color value to fill uvmapping.' +""" + +#---------------------------------------------- +# uvpainter script (c) 04/2004 jean-michel soler +# http://jmsoler.free.fr/util/blenderfile/py/UVpaint05.zip +# this script is released under GPL licence +# for the Blender 2.33 scripts distribution +#---------------------------------------------- +#---------------------------------------------- +# Official page : +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_uvpainting.htm +# Communicate problems and errors on: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#---------------------------------------------- +# Page officielle : +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_uvpainting.htm +# Communiquer les problemes et erreurs sur: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#--------------------------------------------- +# ce script est proposé sous licence GPL pour etre associe +# a la distribution de Blender 2.33 et suivant +#---------------------------------------------- + +import Blender +from Blender.Draw import * +from Blender.BGL import * +from Blender.NMesh import * + +try: + import nt + os=nt +except: + import posix + os=posix + +def exist(path): + try: + pth=os.stat(Blender.sys.dirname(path)) + except: + return 0 + return 1 + +loc0= Blender.sys.dirname(Blender.Get ("filename")) +loc2=loc0+Blender.sys.dirsep+'test00.tga' + +glCr=glRasterPos2d +glCl3=glColor3f +glCl4=glColor4f +glRct=glRectf + +xlimit=0 +selmatlist=[] + +def triangle(a,b,c): + glBegin(GL_TRIANGLES); + glColor3f(a[2],a[3],a[4]) + glVertex2f(a[0],a[1]); + glColor3f(b[2],b[3],b[4]) + glVertex2f(b[0],b[1]); + glColor3f(c[2],c[3],c[4]) + glVertex2f(c[0],c[1]); + glEnd(); + +def Ltriangle(a,b,c): + glBegin(GL_LINES); + glColor3f(1.0,1.0,1.0) + glVertex2f(a[0],a[1]); + glVertex2f(b[0],b[1]); + glVertex2f(c[0],c[1]); + glEnd(); + +def carre(a,b,c,d): + triangle(a,b,c) + triangle(a,c,d) + +def Lcarre(a,b,c,d): + glBegin(GL_LINES); + glColor3f(1.0,1.0,1.0) + glVertex2f(a[0],a[1]); + glVertex2f(b[0],b[1]); + glVertex2f(c[0],c[1]); + glVertex2f(d[0],d[1]); + glEnd(); + + + +def transface(f,x,y): + global xlimit + + + + a=[0,0,0.0, 0.0,0.0,0.0] + b=[0,0,0.0, 0.0,0.0,0.0] + c=[0,0,0.0, 0.0,0.0,0.0] + d=[0,0,0.0, 0.0,0.0,0.0] + + if len(f.v)>=3: + a[0]=int(f.uv[0][0]*x) + a[1]=int(f.uv[0][1]*y) + + if a[0]>xlimit: + xlimit=a[0] + + a[2]=f.col[0].r/255.0 + a[3]=f.col[0].g/255.0 + a[4]=f.col[0].b/255.0 + + c[0]=int(f.uv[2][0]*x) + c[1]=int(f.uv[2][1]*y) + + if c[0]>xlimit: + xlimit=c[0] + + c[2]=f.col[2].r/255.0 + c[3]=f.col[2].g/255.0 + c[4]=f.col[2].b/255.0 + + + b[0]=int(f.uv[1][0]*x) + b[1]=int(f.uv[1][1]*y) + + if b[0]>xlimit: + xlimit=b[0] + + b[2]=f.col[1].r/255.0 + b[3]=f.col[1].g/255.0 + b[4]=f.col[1].b/255.0 + + + if len(f.v)==4: + d[0]=int(f.uv[3][0]*x) + d[1]=int(f.uv[3][1]*y) + + if d[0]>xlimit: + xlimit=d[0] + + d[2]=f.col[3].r/255.0 + d[3]=f.col[3].g/255.0 + d[4]=f.col[3].b/255.0 + else: + d=0 + + + #print a,b,c + return a,b,c,d + + +def extract_faces(me,MENU): + global TMATList, selmatlist + if MENU==2: + listf=[] + for f in me.faces: + if f.mat in selmatlist: + listf.append(f) + return listf + +def affiche_mesh(ME,x,y): + global LINE,xlimit,MMENU,XLIMIT,xwin,xlimit + + if ME.getType()=='Mesh': + me=GetRaw(ME.getData().name) + + if MMENU.val==1: + se=me.faces + + elif MMENU.val==3: + se=me.getSelectedFaces() + + elif MMENU.val==2: + se=extract_faces(me,2) + + xlimit=0 + for f in se: + a,b,c,d=transface(f,x,y) + if len(f.v)==4: + triangle(a,b,c) + triangle(a,c,d) + elif len(f.v)==3: + triangle(a,b,c) + + if LINE.val==1: + for f in se: + a,b,c,d=transface(f,x,y) + if len(f.v)==4: + Lcarre(a,b,c,d) + elif len(f.v)==3: + Ltriangle(a,b,c) + + if XLIMIT.val==0: + Lcarre([1,1],[1,y-2],[xlimit+2,y-2],[xlimit+2,1]) + else: + Lcarre([1,1],[1,y-2],[xwin-2,y-2],[xwin-2,1]) + + + +def write_tgafile(loc2,bitmap,width,height,profondeur): + + f=open(loc2,'wb') + Origine_en_haut_a_gauche=32 + Origine_en_bas_a_gauche=0 + Data_Type_2=2 + RVB=profondeur*8 + RVBA=32 + entete0=[] + for t in range(18): + entete0.append(chr(0)) + + entete0[2]=chr(Data_Type_2) + entete0[13]=chr(width/256) + entete0[12]=chr(width % 256) + entete0[15]=chr(height/256) + entete0[14]=chr(height % 256) + entete0[16]=chr(RVB) + entete0[17]=chr(Origine_en_bas_a_gauche) + + #Origine_en_haut_a_gauche + + for t in entete0: + f.write(t) + + for t in bitmap: + + for c in [2,1,0,3]: + #print t[c]%256 + f.write(chr(t[c]*2)) + f.close() + + +def save(x0,y0,dx,dy): + im = Buffer(GL_BYTE,[dx*(dy+1),4]) + glReadPixels(x0,y0,dx,dy,GL_RGBA, GL_BYTE,im); + print len(im), dx*dy, dx, dy, len(im)/dy + write_tgafile(loc2,im,dx,dy+1,4) + +def DOCMat_list(TMATList,ME): + me=Blender.NMesh.GetRaw(ME.getData().name) + if len(me.materials)!=0: + n=0 + for mat in me.materials: + TMATList[1][n][0]=mat.R + TMATList[1][n][1]=mat.G + TMATList[1][n][2]=mat.B + n+=1 + TMATList[0]=n + else: + TMATList[0]=0 + return TMATList + +def SELMat_list(): + global TMATList,selmatlist + Me=Blender.Object.GetSelected() + if Me!=[]: + if Me[0].getType()=='Mesh': + TMATList=DOCMat_list(TMATList,Me[0]) + selmatlist=[] + for TMat in TMATList[2]: + if TMat.val==1.0: + selmatlist.append(TMATList[2].index(TMat)) + ERROR=0 + else: + ERROR=1 + TextERROR='Selected Object is not a mesh.' + else: + ERROR=1 + TextERROR='No Selected Object.' + +def DOCBONEMENU(TBONEMENU): + pass + +# ---------- +# uvpaint1 +# ---------- +NSIZE=Create(1.0) +# ---------- +# uvpaint2 +# ---------- +LINE=Create(0) +# ---------- +# uvpaint3 +# ---------- +TEXT=Create(loc2) +# ---------- +# uvpaint4 +# ---------- +TMENU="MODE MENU %t|All %x1|Material %x2|Selected %x3" + +# coming soon : "|Bone %x4", perhaps in uvpainter v0.5 + +MMENU=Create(3) +TDOCMat = Create(0) +# ---------- +TMATList= [0,[],[]] +for t in range(16): + TMATList[1].append([0.0,0.0,0.0]) + TMATList[2].append(Create(0)) +# ---------- +TDOCMat = Create(1) +# ---------- +TBONEMENU= Create(1) +# ---------- + +XLIMIT=Create(0) + +y=0 +x=0 +x0=0 +y0=0 +xwin=0 + +n0=32 + +def draw(): + global NSIZE,LINE,x0,y0,y,x,TEXT,MMENU,TDOCMat + global XLIMIT,selmatlist,xwin + + size=Buffer(GL_FLOAT, 4) + glGetFloatv(GL_SCISSOR_BOX, size) + size= size.list + + for s in [0,1,2,3]: size[s]=int(size[s]) + + n0=32 + x0=size[0] + y0=size[1] + + x=size[2] + y=size[3] + + xwin=x + ywin=y + + + glClear(GL_COLOR_BUFFER_BIT) + + glShadeModel(GL_SMOOTH) + SelecMESH=Blender.Object.GetSelected() + if SelecMESH!=[]: + if SelecMESH[0].getType()=='Mesh': + affiche_mesh(SelecMESH[0],int(y*NSIZE.val),int(y*NSIZE.val-n0-2)) + + glColor3f(0.0,0.0,0.0) + glRectf(4,size[3],555,size[3]-32 ) + + glColor3f(1.0,1.0,1.0) + + glRasterPos2f(8, size[3]-13) + Text("uvpainter v0.5") + + glRasterPos2f(8, size[3]-28) + Text("Jm Soler, 05/2004") + + Button("ReDraw" ,16 ,290-118+61 ,size[3]-30 ,60 ,13) + Button("Exit" ,1 ,250-122+63 ,size[3]-30 ,38 ,13) + Button("Save" ,6 ,250-16+61 ,size[3]-30 ,40 ,13) + + NSIZE= Slider("Sc:",4 ,290-118+61 ,size[3]-15 , 102, 13, NSIZE.val, 0.1,1.5,0,"SIZE.") + LINE=Toggle("line", 5 ,250-122+63 ,size[3]-15 , 38, 13, LINE.val, "Draw lines") + + glRasterPos2f(250-130 ,size[3]-13,) + Text("Mode") + + MMENU= Menu(TMENU ,2 ,250-130, size[3]-30, 63, 13, MMENU.val, "MODE menu.") + + if MMENU.val==1 or MMENU.val==3: + glRasterPos2f( 250-16+61+42+80,size[3]-13) + if XLIMIT.val: + xl=xwin + else: + xl=xlimit + + Text("x :"+"%d"%(xl+2)) + + glRasterPos2f(250-16+61+42+65*2,size[3]-13) + Text("y :"+"%d"%(y-n0+1)) + + TEXT=String("to:", 7 , 278+61 ,size[3]-28 , 213, 13, TEXT.val, 256, "Draw lines") + if XLIMIT.val==1: + limit='winlimit' + else: + limit='maxXlimit' + XLIMIT=Toggle(limit, 9 , 250-16+61+42 ,size[3]-15 , 60, 13, XLIMIT.val, "to save picture from x max uv limit, or x window max limit") + + if MMENU.val==2: + TDOCMat=Toggle("doc" ,24,250-130+35 ,size[3]-13 , 28, 13, TDOCMat.val) + if TDOCMat.val==1: + SELMat_list() + for t in range(TMATList[0]): + glCl3(TMATList[1][t][0], + TMATList[1][t][1], + TMATList[1][t][2]) + glRct((293-16+61)+t*20, + size[3]-13, + (293-16+61)+t*20+20, + size[3]-30,) + TMATList[2][t]=Toggle("%s"%t , 32+t ,(293-16+61)+t*20 ,size[3]-13 ,20 , 13,TMATList[2][t].val) + + + +def event(evt, val): + if (evt== QKEY and not val): Exit() + +def bevent(evt): + global LINE,NSIZE,n0,x0,y0,y,TEXT, loc2 + global TMATList, selmatlist, TDOCMat,XLIMIT + global xlimit + + if (evt== 1): + Exit() + + elif (evt== 16): + pass + + elif (evt== 4): + ng=NSIZE.val + + elif (evt== 6): + if XLIMIT.val==1: + xi=xwin + else: + xi=xlimit + + save(x0,y0,xi+2,int(y*NSIZE.val-n0)) + + elif (evt== 7): + if exist(TEXT.val): + loc2=TEXT.val + else: + TEXT.val=loc2 + + elif (evt== 24) or (evt in [32,33,34,35,36,37,38,39,40,41,42,43,44]): + SELMat_list() + + + Blender.Redraw() + +Register(draw, event, bevent) diff --git a/release/scripts/ac3d_export.py b/release/scripts/ac3d_export.py index 6a464767c4c..04da0d38cab 100644 --- a/release/scripts/ac3d_export.py +++ b/release/scripts/ac3d_export.py @@ -16,7 +16,7 @@ Tip: 'Export to AC3D (.ac) format.' # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # -# Copyright (C) 2004: Willian P. Germano, wgermano@ig.com.br +# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/release/scripts/ac3d_import.py b/release/scripts/ac3d_import.py index 3e3d08a1155..3dc8af7ad2c 100644 --- a/release/scripts/ac3d_import.py +++ b/release/scripts/ac3d_import.py @@ -13,7 +13,7 @@ Tip: 'Import an AC3D (.ac) file.' # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # -# Copyright (C) 2004: Willian P. Germano, wgermano@ig.com.br +# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/release/scripts/disp_paint233f.py b/release/scripts/disp_paint233f.py new file mode 100644 index 00000000000..cf60f4ecfae --- /dev/null +++ b/release/scripts/disp_paint233f.py @@ -0,0 +1,329 @@ +#!BPY + +""" Registration info for Blender menus: <- these words are ignored +Name: 'Dispaint' +Blender: 233 +Group: 'Modifiers' +Tip: 'use vertex paint color value to modify shape displacing vertices along normal.' +""" + +#---------------------------------------------- +# jm soler, displacement paint 03/2002 - > 05/2004: disp_paintf +#---------------------------------------------- +# Official page : +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_displacementpainting.htm +#---------------------------------------------- +# Communicate problems and errors on: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#--------------------------------------------- +# this script is released under GPL licence +# for the Blender 2.33 scripts package +#---------------------------------------------- +# Page officielle : +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_displacementpainting.htm +# Communiquer les problemes et erreurs sur: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#--------------------------------------------- +# ce script est proposé sous licence GPL pour etre associe +# a la distribution de Blender 2.33 +#---------------------------------------------- + +import Blender +from Blender import * +from Blender.Draw import * +from Blender.BGL import * + + +# niveau du deplacement +ng=0.5 + +# profondeur des couleurs primaires rgb +maxcol=255.0*3 + +# limitation de la zone de travail sur le +# le materiau numer mat du tableau d'indices +# des materiaux. Par defaut mat =-1 ce qui signifie +# que toute la surface est traitee +mat=[] +vindex=[] +ORIName='' +NEWName='' +ERROR=0 +TextERROR='' + +def copy_transform(ozero,Obis): + Obis.setSize(ozero.getSize()); + Obis.setEuler(ozero.getEuler()); + Obis.setLocation(ozero.getLocation()) + return Obis + +def traite_face(f): + global vindexm + if ORIENTMenu.val==1: + for z in range(len(f.v)): + c=0.0 + if vindex[f.v[z].index]!=0: + c=float(f.col[z].r+f.col[z].b+f.col[z].g)/maxcol*ng/vindex[f.v[z].index] + else: + c=0 + + f.v[z].co[0]=f.v[z].co[0]+f.v[z].no[0]*c + f.v[z].co[1]=f.v[z].co[1]+f.v[z].no[1]*c + f.v[z].co[2]=f.v[z].co[2]+f.v[z].no[2]*c + + if ORIENTMenu.val==2: + for z in range(len(f.v)): + c=0.0 + if vindex[f.v[z].index]!=0: + c=float(f.col[z].r+f.col[z].b+f.col[z].g)/maxcol*ng/vindex[f.v[z].index] + else: + c=0 + for t in range(3): + if TAXEList[1][t].val==1: + f.v[z].co[t]=f.v[z].co[t]+c + + +def paint(): + global MODEMenu, vindex,ng, mat, ORIName, NEWName + + Me=Object.GetSelected() + if Me!=[]: + if Me[0].getType()=='Mesh': + + vindex=[] + ORIName=Me[0].getData().name + me=NMesh.GetRaw(Me[0].getData().name) + + name='new.002' + + for m in me.verts: + vindex.append(0) + + for f in me.faces: + for v in f.v: + if MODEMenu.val!=2: + if MODEMenu.val==1: + vindex[v.index]+=1 + else: + if v.sel==1: + vindex[v.index]+=1 + else: + #print mat + if f.mat in mat: + vindex[v.index]+=1 + + for f in me.faces: + if MODEMenu.val==2: + if f.mat in mat: + traite_face(f) + else: + traite_face(f) + + NMesh.PutRaw(me,name) + + if name!=Object.GetSelected()[0].getData().name: + obj=Object.Get() + for o in obj: + if o.getType()=='Mesh': + if o.getData().name==name: + o.makeDisplayList() + + o=copy_transform(Me[0],o) + """ + o.setEuler(Me[0].getEuler()) + o.setLocation(Me[0].getLocation()) + """ + + else: + Me[0].makeDisplayList() + +def NEWMEcreation(name): + nomdelobjet=""; objnumber=-1; namelist=[] + obj=Object.Get() + + for ozero in obj: + if ozero.getType()=='Mesh': + namelist.append(ozero.getData().name) + if ozero.getData().name==name: + objnumber=obj.index(ozero) + + if objnumber!=-1: + ozero=obj[objnumber] + nomdelobjet=ozero.getName() + Mesh=Blender.NMesh.GetRawFromObject(nomdelobjet) + + n=0; name2=name[:];ok=0 + + while ok==0: + for n0 in namelist: + if n0.find(name2)==0: + ok=0;name2=name[0:name.find('.')+1]+'%s'%(n+1) + else: ok=1 + n+=1 + Mesh.name=name2 + Obis = Blender.NMesh.PutRaw(Mesh,name2) + copy_transform(ozero,Obis) + Obis.makeDisplayList() + +def DOCMat_list(TMATList): + global mat + Me=Object.GetSelected() + if Me!=[]: + if Me[0].getType()=='Mesh': + me=NMesh.GetRaw(Me[0].getData().name) + if len(me.materials)!=0: + n=0 + for mat in me.materials: + TMATList[1][n][0]=mat.R + TMATList[1][n][1]=mat.G + TMATList[1][n][2]=mat.B + n+=1 + TMATList[0]=n + else: + TMATList[0]=0 + return TMATList + +MOname = "MODE MENU %t|Normal %x1|Material %x2|Selected %x3" +ORname = "ORIENT MENU %t|From Normal %x1|Local Axes %x2" + +MODEMenu = Create(1) +ORIENTMenu = Create(1) +NSIZE = Create(1.0) +TDOCMat = Create(0) +NRepeat = Create(1) + +TMATList= [0,[],[]] + +for t in range(16): + TMATList[1].append([0.0,0.0,0.0]) + TMATList[2].append(Create(0)) + +TAXEList=[['X','Y','Z'],[]] +for t in range(3): + TAXEList[1].append(Create(0)) + +glCr=glRasterPos2d +glCl3=glColor3f +glCl4=glColor4f +glRct=glRectf + + + +def draw(): + global MODEMenu, NSIZE, TDOCMat,TMATList, TAXEList + global mat, ORIName, NEWName, ORIENTMenu + global NRepeat, ERROR, TextERROR + + size=Buffer(GL_FLOAT, 4) + glGetFloatv(GL_SCISSOR_BOX, size) + size= size.list + + for s in [0,1,2,3]: size[s]=int(size[s]) + + glClear(GL_COLOR_BUFFER_BIT) + + glColor3f(0.0,0.0,0.0) + glRectf(4,size[3],534,size[3]-32 ) + + glColor3f(1.0,1.0,1.0) + glRasterPos2f(20, size[3]-15) + Text("Script Python de displacement paintingt") + + glRasterPos2f(20, size[3]-28) + Text("Jean-michel Soler, avril 2004") + + + n0=70 + n1=55 + + Button("Create" ,17 ,5 ,size[3]-n0+16 ,60 ,20) + Button("Action" ,16 ,5 ,size[3]-n0-4 ,60 ,20) + Button("Exit" ,1 ,5 ,size[3]-n0-24 ,60 ,20) + + NRepeat=Number("repeat" ,5 ,5 ,size[3]-n0-50 ,75 ,20, NRepeat.val,1,10) + + glColor3f(0.0,0.0,0.0) + glRasterPos2f(80 ,size[3]-n0+24) + Text("MODE") + + MODEMenu= Menu(MOname, 2 ,80 ,size[3]-n0 ,100,20, MODEMenu.val, "MODE menu.") + + if MODEMenu.val==2: + TDOCMat=Toggle("Doc Mat" ,24 ,180 ,size[3]-n0 ,60 ,20,TDOCMat.val) + if TDOCMat.val==1: + #print TMATList + for t in range(TMATList[0]): + glCl3(TMATList[1][t][0], + TMATList[1][t][1], + TMATList[1][t][2]) + glRct(80+t*40, + size[3]-n0-60, + 80+t*40+40, + size[3]-n0-60+40) + TMATList[2][t]=Toggle("%s"%t , 32+t ,80+t*40+5 ,size[3]-n0-50 ,30 , 20,TMATList[2][t].val) + glColor3f(1.0,0.3,0.0) + glRasterPos2f(80+40+5 ,size[3]-n0-80) + if ERROR==1: + Text('Last error : '+TextERROR) + else: + Text('Last error : ') + + glColor3f(0.0,0.0,0.0) + glRasterPos2f(240 ,size[3]-n0+24) + Text("ORIENTATION") + + ORIENTMenu= Menu(ORname, 3 ,240 ,size[3]-n0 ,100,20, ORIENTMenu.val, "MODE menu.") + if ORIENTMenu.val>1: + for t in range(3): + TAXEList[1][t]=Toggle("%s"%TAXEList[0][t], + 40+t, + 240+100+t*30 , size[3]-n0 ,30 , 20, + TAXEList[1][t].val) + + NSIZE= Slider("Disp Size", 4 ,80 ,size[3]-n0-20 ,260,20, NSIZE.val, -4.0,+4.0,0,"SIZE.") + + + + +def event(evt, val): + if (evt== QKEY and not val): Exit() + +def bevent(evt): + global MODEMenu, NSIZE, ng, TMATList + global mat, ORIENTMenu, NRepeat, TAXEList + global ERROR,TextERROR + + if (evt== 1): + Exit() + + + elif (evt== 16): + for n in range(NRepeat.val): + paint() + + elif (evt== 4): + ng=NSIZE.val + + elif (evt== 24) or (evt in [32,33,34,35,36,37,38,39,40,41,42,43,44]): + Me=Object.GetSelected() + if Me!=[]: + if Me[0].getType()=='Mesh': + TMATList=DOCMat_list(TMATList) + mat=[] + for TMat in TMATList[2]: + if TMat.val==1.0: + mat.append(TMATList[2].index(TMat)) + ERROR=0 + else: + ERROR=1 + TextERROR='Selected Object is not a mesh.' + else: + ERROR=1 + TextERROR='No Selected Object.' + + elif (evt== 17): + NEWMEcreation('new.002') + + Blender.Redraw() + +Register(draw, event, bevent) diff --git a/release/scripts/fixfromarmature.py b/release/scripts/fixfromarmature.py new file mode 100644 index 00000000000..564e56ff66e --- /dev/null +++ b/release/scripts/fixfromarmature.py @@ -0,0 +1,37 @@ +#!BPY + +""" Registration info for Blender menus: <- these words are ignored +Name: 'Fix from Armature' +Blender: 232 +Group: 'Generators' +Tip: 'Fix armature deformation.' +""" + +#---------------------------------------------- +# jm soler 05/2004 : 'FixfromArmature' +#---------------------------------------------- +# Official Page : +# http://jmsoler.free.fr/util/blenderfile/py/fixfromarmature.py +# Communicate problems and errors on: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#--------------------------------------------- +# Page officielle : +# http://jmsoler.free.fr/util/blenderfile/py/fixfromarmature.py +# Communiquer les problemes et erreurs sur: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#--------------------------------------------- + +import Blender +try: + Ozero=Blender.Object.GetSelected()[0] + nomdelobjet=Ozero.getName() + Mesh=Blender.NMesh.GetRawFromObject(nomdelobjet) + Obis = Blender.Object.New ('Mesh') + Obis.link(Mesh) + Obis.setSize(Ozero.getSize()) + Obis.setEuler(Ozero.getEuler()) + Obis.setLocation(Ozero.getMatrix()[3][0:3]) + scene = Blender.Scene.getCurrent() + scene.link (Obis) +except: + print "not a mesh or no object selected" diff --git a/release/scripts/lightwave_export.py b/release/scripts/lightwave_export.py new file mode 100644 index 00000000000..6ed96300673 --- /dev/null +++ b/release/scripts/lightwave_export.py @@ -0,0 +1,528 @@ +#!BPY + +""" +Name: 'LightWave...' +Blender: 232 +Group: 'Export' +Tooltip: 'Export selected meshes to LightWave File Format (*.lwo)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2002 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | April 21, 2002 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write LightWave Object File Format (*.lwo) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, chunk, os, cStringIO, time, operator + +# ============================== +# === Write LightWave Format === +# ============================== +def write(filename): + start = time.clock() + file = open(filename, "wb") + + objects = Blender.Object.GetSelected() + objects.sort(lambda a,b: cmp(a.name, b.name)) + if not objects: + mod_meshtools.print_boxed("No mesh objects are selected.") + return + + if len(objects) > 20 and mod_meshtools.show_progress: + mod_meshtools.show_progress = 0 + + text = generate_text() + desc = generate_desc() + icon = "" #generate_icon() + + material_names = get_used_material_names(objects) + tags = generate_tags(material_names) + surfs = generate_surfs(material_names) + chunks = [text, desc, icon, tags] + + meshdata = cStringIO.StringIO() + layer_index = 0 + for object in objects: + objname = object.name + meshname = object.data.name + mesh = Blender.NMesh.GetRaw(meshname) + #mesh = Blender.NMesh.GetRawFromObject(meshname) # for SubSurf + obj = Blender.Object.Get(objname) + if not mesh: continue + + layr = generate_layr(objname, layer_index) + pnts = generate_pnts(mesh, obj.matrix) + bbox = generate_bbox(mesh) + pols = generate_pols(mesh) + ptag = generate_ptag(mesh, material_names) + + if mesh.hasFaceUV(): + vmad_uv = generate_vmad_uv(mesh) # per face + + if mod_meshtools.has_vertex_colors(mesh): + if mod_meshtools.average_vcols: + vmap_vc = generate_vmap_vc(mesh) # per vert + else: + vmad_vc = generate_vmad_vc(mesh) # per face + + write_chunk(meshdata, "LAYR", layr); chunks.append(layr) + write_chunk(meshdata, "PNTS", pnts); chunks.append(pnts) + write_chunk(meshdata, "BBOX", bbox); chunks.append(bbox) + write_chunk(meshdata, "POLS", pols); chunks.append(pols) + write_chunk(meshdata, "PTAG", ptag); chunks.append(ptag) + + if mesh.hasFaceUV(): + write_chunk(meshdata, "VMAD", vmad_uv) + chunks.append(vmad_uv) + + if mod_meshtools.has_vertex_colors(mesh): + if mod_meshtools.average_vcols: + write_chunk(meshdata, "VMAP", vmap_vc) + chunks.append(vmap_vc) + else: + write_chunk(meshdata, "VMAD", vmad_vc) + chunks.append(vmad_vc) + layer_index += 1 + + for surf in surfs: + chunks.append(surf) + + write_header(file, chunks) + write_chunk(file, "ICON", icon) + write_chunk(file, "TEXT", text) + write_chunk(file, "DESC", desc) + write_chunk(file, "TAGS", tags) + file.write(meshdata.getvalue()); meshdata.close() + for surf in surfs: + write_chunk(file, "SURF", surf) + + Blender.Window.DrawProgressBar(1.0, "") # clear progressbar + file.close() + print '\a\r', + end = time.clock() + seconds = " in %.2f %s" % (end-start, "seconds") + message = "Successfully exported " + os.path.basename(filename) + seconds + mod_meshtools.print_boxed(message) + +# ======================================= +# === Generate Null-Terminated String === +# ======================================= +def generate_nstring(string): + if len(string)%2 == 0: # even + string += "\0\0" + else: # odd + string += "\0" + return string + +# =============================== +# === Get Used Material Names === +# =============================== +def get_used_material_names(objects): + matnames = {} + for object in objects: + objname = object.name + meshname = object.data.name + mesh = Blender.NMesh.GetRaw(meshname) + if not mesh: continue + if (not mesh.materials) and (mod_meshtools.has_vertex_colors(mesh)): + # vcols only + if mod_meshtools.average_vcols: + matnames["\251 Per-Vert Vertex Colors"] = None + else: + matnames["\251 Per-Face Vertex Colors"] = None + elif (mesh.materials) and (not mod_meshtools.has_vertex_colors(mesh)): + # materials only + for material in mesh.materials: + matnames[material.name] = None + elif (not mesh.materials) and (not mod_meshtools.has_vertex_colors(mesh)): + # neither + matnames["\251 Blender Default"] = None + else: + # both + for material in mesh.materials: + matnames[material.name] = None + return matnames + +# ========================================= +# === Generate Tag Strings (TAGS Chunk) === +# ========================================= +def generate_tags(material_names): + material_names = map(generate_nstring, material_names.keys()) + tags_data = reduce(operator.add, material_names) + return tags_data + +# ======================== +# === Generate Surface === +# ======================== +def generate_surface(name, mesh): + if name.find("\251 Per-") == 0: + return generate_vcol_surf(mesh) + elif name == "\251 Blender Default": + return generate_default_surf() + else: + return generate_surf(name) + +# ====================== +# === Generate Surfs === +# ====================== +def generate_surfs(material_names): + keys = material_names.keys() + values = material_names.values() + surfaces = map(generate_surface, keys, values) + return surfaces + +# =================================== +# === Generate Layer (LAYR Chunk) === +# =================================== +def generate_layr(name, idx): + data = cStringIO.StringIO() + data.write(struct.pack(">h", idx)) # layer number + data.write(struct.pack(">h", 0)) # flags + data.write(struct.pack(">fff", 0, 0, 0)) # pivot + data.write(generate_nstring(name)) # name + return data.getvalue() + +# =================================== +# === Generate Verts (PNTS Chunk) === +# =================================== +def generate_pnts(mesh, matrix): + data = cStringIO.StringIO() + for i in range(len(mesh.verts)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts") + x, y, z = mod_meshtools.apply_transform(mesh.verts[i].co, matrix) + data.write(struct.pack(">fff", x, z, y)) + return data.getvalue() + +# ========================================== +# === Generate Bounding Box (BBOX Chunk) === +# ========================================== +def generate_bbox(mesh): + data = cStringIO.StringIO() + # need to transform verts here + nv = map(getattr, mesh.verts, ["co"]*len(mesh.verts)) + xx = map(operator.getitem, nv, [0]*len(nv)) + yy = map(operator.getitem, nv, [1]*len(nv)) + zz = map(operator.getitem, nv, [2]*len(nv)) + data.write(struct.pack(">6f", min(xx), min(zz), min(yy), max(xx), max(zz), max(yy))) + return data.getvalue() + +# ======================================== +# === Average All Vertex Colors (Fast) === +# ======================================== +def average_vertexcolors(mesh): + vertexcolors = {} + vcolor_add = lambda u, v: [u[0]+v[0], u[1]+v[1], u[2]+v[2], u[3]+v[3]] + vcolor_div = lambda u, s: [u[0]/s, u[1]/s, u[2]/s, u[3]/s] + for i in range(len(mesh.faces)): # get all vcolors that share this vertex + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Finding Shared VColors") + for j in range(len(mesh.faces[i].v)): + index = mesh.faces[i].v[j].index + color = mesh.faces[i].col[j] + r,g,b,a = color.r, color.g, color.b, color.a + vertexcolors.setdefault(index, []).append([r,g,b,a]) + for i in range(len(vertexcolors)): # average them + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") + vcolor = [0,0,0,0] # rgba + for j in range(len(vertexcolors[i])): + vcolor = vcolor_add(vcolor, vertexcolors[i][j]) + shared = len(vertexcolors[i]) + vertexcolors[i] = vcolor_div(vcolor, shared) + return vertexcolors + +# ==================================================== +# === Generate Per-Vert Vertex Colors (VMAP Chunk) === +# ==================================================== +def generate_vmap_vc(mesh): + data = cStringIO.StringIO() + data.write("RGB ") # type + data.write(struct.pack(">H", 3)) # dimension + data.write(generate_nstring("Blender's Vertex Colors")) # name + vertexcolors = average_vertexcolors(mesh) + for i in range(len(vertexcolors)): + r, g, b, a = vertexcolors[i] + data.write(struct.pack(">H", i)) # vertex index + data.write(struct.pack(">fff", r/255.0, g/255.0, b/255.0)) + return data.getvalue() + +# ==================================================== +# === Generate Per-Face Vertex Colors (VMAD Chunk) === +# ==================================================== +def generate_vmad_vc(mesh): + data = cStringIO.StringIO() + data.write("RGB ") # type + data.write(struct.pack(">H", 3)) # dimension + data.write(generate_nstring("Blender's Vertex Colors")) # name + for i in range(len(mesh.faces)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Vertex Colors") + numfaceverts = len(mesh.faces[i].v) + for j in range(numfaceverts-1, -1, -1): # Reverse order + r = mesh.faces[i].col[j].r + g = mesh.faces[i].col[j].g + b = mesh.faces[i].col[j].b + v = mesh.faces[i].v[j].index + data.write(struct.pack(">H", v)) # vertex index + data.write(struct.pack(">H", i)) # face index + data.write(struct.pack(">fff", r/255.0, g/255.0, b/255.0)) + return data.getvalue() + +# ================================================ +# === Generate Per-Face UV Coords (VMAD Chunk) === +# ================================================ +def generate_vmad_uv(mesh): + data = cStringIO.StringIO() + data.write("TXUV") # type + data.write(struct.pack(">H", 2)) # dimension + data.write(generate_nstring("Blender's UV Coordinates")) # name + for i in range(len(mesh.faces)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing UV Coordinates") + numfaceverts = len(mesh.faces[i].v) + for j in range(numfaceverts-1, -1, -1): # Reverse order + U,V = mesh.faces[i].uv[j] + v = mesh.faces[i].v[j].index + data.write(struct.pack(">H", v)) # vertex index + data.write(struct.pack(">H", i)) # face index + data.write(struct.pack(">ff", U, V)) + return data.getvalue() + +# ====================================== +# === Generate Variable-Length Index === +# ====================================== +def generate_vx(index): + if index < 0xFF00: + value = struct.pack(">H", index) # 2-byte index + else: + value = struct.pack(">L", index | 0xFF000000) # 4-byte index + return value + +# =================================== +# === Generate Faces (POLS Chunk) === +# =================================== +def generate_pols(mesh): + data = cStringIO.StringIO() + data.write("FACE") # polygon type + for i in range(len(mesh.faces)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces") + data.write(struct.pack(">H", len(mesh.faces[i].v))) # numfaceverts + numfaceverts = len(mesh.faces[i].v) + for j in range(numfaceverts-1, -1, -1): # Reverse order + index = mesh.faces[i].v[j].index + data.write(generate_vx(index)) + return data.getvalue() + +# ================================================= +# === Generate Polygon Tag Mapping (PTAG Chunk) === +# ================================================= +def generate_ptag(mesh, material_names): + data = cStringIO.StringIO() + data.write("SURF") # polygon tag type + for i in range(len(mesh.faces)): # numfaces + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Surface Indices") + data.write(generate_vx(i)) + if (not mesh.materials) and (mod_meshtools.has_vertex_colors(mesh)): # vcols only + if mod_meshtools.average_vcols: + name = "\251 Per-Vert Vertex Colors" + else: + name = "\251 Per-Face Vertex Colors" + elif (mesh.materials) and (not mod_meshtools.has_vertex_colors(mesh)): # materials only + idx = mesh.faces[i].mat #erialIndex + name = mesh.materials[idx].name + elif (not mesh.materials) and (not mod_meshtools.has_vertex_colors(mesh)): # neither + name = "\251 Blender Default" + else: # both + idx = mesh.faces[i].mat + name = mesh.materials[idx].name + names = material_names.keys() + surfidx = names.index(name) + data.write(struct.pack(">H", surfidx)) # surface index + return data.getvalue() + +# =================================================== +# === Generate VC Surface Definition (SURF Chunk) === +# =================================================== +def generate_vcol_surf(mesh): + data = cStringIO.StringIO() + if mod_meshtools.average_vcols and mod_meshtools.has_vertex_colors(mesh): + surface_name = generate_nstring("\251 Per-Vert Vertex Colors") + else: + surface_name = generate_nstring("\251 Per-Face Vertex Colors") + data.write(surface_name) + data.write("\0\0") + + data.write("COLR") + data.write(struct.pack(">H", 14)) + data.write(struct.pack(">fffH", 1, 1, 1, 0)) + + data.write("DIFF") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", 0.0, 0)) + + data.write("LUMI") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", 1.0, 0)) + + data.write("VCOL") + data.write(struct.pack(">H", 34)) + data.write(struct.pack(">fH4s", 1.0, 0, "RGB ")) # intensity, envelope, type + data.write(generate_nstring("Blender's Vertex Colors")) # name + + data.write("CMNT") # material comment + comment = "Vertex Colors: Exported from Blender\256 " + mod_meshtools.blender_version_str + comment = generate_nstring(comment) + data.write(struct.pack(">H", len(comment))) + data.write(comment) + return data.getvalue() + +# ================================================ +# === Generate Surface Definition (SURF Chunk) === +# ================================================ +def generate_surf(material_name): + data = cStringIO.StringIO() + data.write(generate_nstring(material_name)) + data.write("\0\0") + + material = Blender.Material.Get(material_name) + R,G,B = material.R, material.G, material.B + data.write("COLR") + data.write(struct.pack(">H", 14)) + data.write(struct.pack(">fffH", R, G, B, 0)) + + data.write("DIFF") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", material.ref, 0)) + + data.write("LUMI") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", material.emit, 0)) + + data.write("SPEC") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", material.spec, 0)) + + data.write("GLOS") + data.write(struct.pack(">H", 6)) + gloss = material.hard / (255/2.0) + gloss = round(gloss, 1) + data.write(struct.pack(">fH", gloss, 0)) + + data.write("CMNT") # material comment + comment = material_name + ": Exported from Blender\256 " + mod_meshtools.blender_version_str + comment = generate_nstring(comment) + data.write(struct.pack(">H", len(comment))) + data.write(comment) + return data.getvalue() + +# ============================================= +# === Generate Default Surface (SURF Chunk) === +# ============================================= +def generate_default_surf(): + data = cStringIO.StringIO() + material_name = "\251 Blender Default" + data.write(generate_nstring(material_name)) + data.write("\0\0") + + data.write("COLR") + data.write(struct.pack(">H", 14)) + data.write(struct.pack(">fffH", 1, 1, 1, 0)) + + data.write("DIFF") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", 0.8, 0)) + + data.write("LUMI") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", 0, 0)) + + data.write("SPEC") + data.write(struct.pack(">H", 6)) + data.write(struct.pack(">fH", 0.5, 0)) + + data.write("GLOS") + data.write(struct.pack(">H", 6)) + gloss = 50 / (255/2.0) + gloss = round(gloss, 1) + data.write(struct.pack(">fH", gloss, 0)) + + data.write("CMNT") # material comment + comment = material_name + ": Exported from Blender\256 " + mod_meshtools.blender_version_str + + # vals = map(chr, range(164,255,1)) + # keys = range(164,255,1) + # keys = map(lambda x: `x`, keys) + # comment = map(None, keys, vals) + # comment = reduce(operator.add, comment) + # comment = reduce(operator.add, comment) + + comment = generate_nstring(comment) + data.write(struct.pack(">H", len(comment))) + data.write(comment) + return data.getvalue() + +# ============================================ +# === Generate Object Comment (TEXT Chunk) === +# ============================================ +def generate_text(): + comment = "Lightwave Export Script for Blender " + comment += mod_meshtools.blender_version_str + "\n" + comment += "by Anthony D'Agostino\n" + comment += "scorpius@netzero.com\n" + comment += "http://ourworld.compuserve.com/homepages/scorpius\n" + return generate_nstring(comment) + +# ============================================== +# === Generate Description Line (DESC Chunk) === +# ============================================== +def generate_desc(): + comment = "Copyright 2002 Scorpius Entertainment" + return generate_nstring(comment) + +# ================================================== +# === Generate Thumbnail Icon Image (ICON Chunk) === +# ================================================== +def generate_icon(): + data = cStringIO.StringIO() + file = open("f:/obj/radiosity/lwo2_icon.tga", "rb") # 60x60 uncompressed TGA + file.read(18) + icon_data = file.read(3600) # ? + file.close() + data.write(struct.pack(">HH", 0, 60)) + data.write(icon_data) + #print len(icon_data) + return data.getvalue() + +# =================== +# === Write Chunk === +# =================== +def write_chunk(file, name, data): + file.write(name) + file.write(struct.pack(">L", len(data))) + file.write(data) + +# ============================= +# === Write LWO File Header === +# ============================= +def write_header(file, chunks): + chunk_sizes = map(len, chunks) + chunk_sizes = reduce(operator.add, chunk_sizes) + form_size = chunk_sizes + len(chunks)*8 + len("FORM") + file.write("FORM") + file.write(struct.pack(">L", form_size)) + file.write("LWO2") + +def fs_callback(filename): + if filename.find('.lwo', -4) <= 0: filename += '.lwo' + write(filename) + +Blender.Window.FileSelector(fs_callback, "LWO Export") diff --git a/release/scripts/lightwave_import.py b/release/scripts/lightwave_import.py new file mode 100644 index 00000000000..5bfef5c907a --- /dev/null +++ b/release/scripts/lightwave_import.py @@ -0,0 +1,172 @@ +#!BPY + +""" +Name: 'LightWave...' +Blender: 232 +Group: 'Import' +Tooltip: 'Import LightWave Object File Format (*.lwo)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2002 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | April 21, 2002 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write LightWave Object File Format (*.lwo) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, chunk, os, cStringIO, time, operator + +# ============================= +# === Read LightWave Format === +# ============================= +def read(filename): + start = time.clock() + file = open(filename, "rb") + + # === LWO header === + form_id, form_size, form_type = struct.unpack(">4s1L4s", file.read(12)) + if (form_type != "LWOB") and (form_type != "LWO2"): + print "Can't read a file with the form_type:", form_type + return + + objname = os.path.splitext(os.path.basename(filename))[0] + + while 1: + try: + lwochunk = chunk.Chunk(file) + except EOFError: + break + if lwochunk.chunkname == "LAYR": + objname = read_layr(lwochunk) + elif lwochunk.chunkname == "PNTS": # Verts + verts = read_verts(lwochunk) + elif lwochunk.chunkname == "POLS" and form_type == "LWO2": # Faces v6.0 + faces = read_faces_6(lwochunk) + mod_meshtools.create_mesh(verts, faces, objname) + elif lwochunk.chunkname == "POLS" and form_type == "LWOB": # Faces v5.5 + faces = read_faces_5(lwochunk) + mod_meshtools.create_mesh(verts, faces, objname) + else: # Misc Chunks + lwochunk.skip() + + Blender.Window.DrawProgressBar(1.0, "") # clear progressbar + file.close() + end = time.clock() + seconds = " in %.2f %s" % (end-start, "seconds") + if form_type == "LWO2": fmt = " (v6.0 Format)" + if form_type == "LWOB": fmt = " (v5.5 Format)" + message = "Successfully imported " + os.path.basename(filename) + fmt + seconds + mod_meshtools.print_boxed(message) + +# ================== +# === Read Verts === +# ================== +def read_verts(lwochunk): + data = cStringIO.StringIO(lwochunk.read()) + numverts = lwochunk.chunksize/12 + #$verts = [] + verts = [None] * numverts + for i in range(numverts): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts") + x, y, z = struct.unpack(">fff", data.read(12)) + #$verts.append((x, z, y)) + verts[i] = (x, z, y) + return verts + +# ================= +# === Read Name === +# ================= +def read_name(file): + name = "" + while 1: + char = file.read(1) + if char == "\0": break + else: name += char + return name + +# ================== +# === Read Layer === +# ================== +def read_layr(lwochunk): + data = cStringIO.StringIO(lwochunk.read()) + idx, flags = struct.unpack(">hh", data.read(4)) + pivot = struct.unpack(">fff", data.read(12)) + layer_name = read_name(data) + if not layer_name: layer_name = "No Name" + return layer_name + +# ====================== +# === Read Faces 5.5 === +# ====================== +def read_faces_5(lwochunk): + data = cStringIO.StringIO(lwochunk.read()) + faces = [] + i = 0 + while i < lwochunk.chunksize: + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading Faces") + facev = [] + numfaceverts, = struct.unpack(">H", data.read(2)) + for j in range(numfaceverts): + index, = struct.unpack(">H", data.read(2)) + facev.append(index) + facev.reverse() + faces.append(facev) + surfaceindex, = struct.unpack(">H", data.read(2)) + if surfaceindex < 0: + print "detail polygons follow, error." + return + i += (4+numfaceverts*2) + return faces + +# ================================== +# === Read Variable-Length Index === +# ================================== +def read_vx(data): + byte1, = struct.unpack(">B", data.read(1)) + if byte1 != 0xFF: # 2-byte index + byte2, = struct.unpack(">B", data.read(1)) + index = byte1*256 + byte2 + index_size = 2 + else: # 4-byte index + byte2, byte3, byte4 = struct.unpack(">3B", data.read(3)) + index = byte2*65536 + byte3*256 + byte4 + index_size = 4 + return index, index_size + +# ====================== +# === Read Faces 6.0 === +# ====================== +def read_faces_6(lwochunk): + data = cStringIO.StringIO(lwochunk.read()) + faces = [] + polygon_type = data.read(4) + if polygon_type != "FACE": + print "No Faces Were Found. Polygon Type:", polygon_type + return "" + i = 0 + while(i < lwochunk.chunksize-4): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading Faces") + facev = [] + numfaceverts, = struct.unpack(">H", data.read(2)) + i += 2 + + for j in range(numfaceverts): + index, index_size = read_vx(data) + i += index_size + facev.append(index) + facev.reverse() + faces.append(facev) + return faces + +def fs_callback(filename): + read(filename) + +Blender.Window.FileSelector(fs_callback, "LWO Import") diff --git a/release/scripts/mod_flags.py b/release/scripts/mod_flags.py deleted file mode 100644 index 810a510181a..00000000000 --- a/release/scripts/mod_flags.py +++ /dev/null @@ -1,19 +0,0 @@ -# +---------------------------------------------------------+ -# | Copyright (c) 2002 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | -# | October 25, 2002 | -# | Released under the Blender Artistic Licence (BAL) | -# | Import Export Suite v0.5 | -# +---------------------------------------------------------+ -# | Share Global Variables Across Modules | -# +---------------------------------------------------------+ - -import Blender - -blender_version = Blender.Get('version') -blender_version_str = `blender_version`[0] + '.' + `blender_version`[1:] - -show_progress = 1 # Set to 0 for faster performance -average_vcols = 1 # Off for per-face, On for per-vertex -overwrite_mesh_name = 0 # Set to 0 for safety diff --git a/release/scripts/mod_meshtools.py b/release/scripts/mod_meshtools.py index dbcdab513d5..95dae16b562 100644 --- a/release/scripts/mod_meshtools.py +++ b/release/scripts/mod_meshtools.py @@ -1,88 +1,93 @@ # +---------------------------------------------------------+ # | Copyright (c) 2001 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve. | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | September 28, 2002 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | # +---------------------------------------------------------+ -# | Common Functions For All Modules | +# | Common Functions & Global Variables For All IO Modules | # +---------------------------------------------------------+ import Blender -import sys#, random, operator -import mod_flags +import sys + +show_progress = 1 # Set to 0 for faster performance +average_vcols = 1 # Off for per-face, On for per-vertex +overwrite_mesh_name = 0 # Set to 0 to increment object-name version + +blender_version = Blender.Get('version') +blender_version_str = `blender_version`[0] + '.' + `blender_version`[1:] try: - import random, operator -# =================================== -# ==== Append Faces To Face List ==== -# =================================== - def append_faces(mesh, faces, facesuv, uvcoords): - r = random.randrange(200, 255, 50) - g = random.randrange(100, 200, 50) - b = random.randrange(0, 100, 50) - for i in range(len(faces)): - if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(faces), "Generating Faces") - numfaceverts=len(faces[i]) - if numfaceverts <= 4: # This face is a triangle or quad + import operator +except: + msg = "Error: you need a full Python install to run this script." + mod_meshtools.print_boxed(msg) + Blender.Draw.PupMenu("ERROR%t|"+msg) + +# ================================= +# === Append Faces To Face List === +# ================================= +def append_faces(mesh, faces, facesuv, uvcoords): + for i in range(len(faces)): + if not i%100 and show_progress: Blender.Window.DrawProgressBar(float(i)/len(faces), "Generating Faces") + numfaceverts=len(faces[i]) + if numfaceverts <= 4: # This face is a triangle or quad + face = Blender.NMesh.Face() + for j in range(numfaceverts): + index = faces[i][j] + face.v.append(mesh.verts[index]) + if len(uvcoords) > 1: + uvidx = facesuv[i][j] + face.uv.append(uvcoords[uvidx]) + face.mode = 0 + face.col = [Blender.NMesh.Col()]*4 + mesh.faces.append(face) + else: # Triangulate n-sided convex polygon. + a, b, c = 0, 1, 2 # Indices of first triangle. + for j in range(numfaceverts-2): # Number of triangles in polygon. face = Blender.NMesh.Face() - for j in range(numfaceverts): - index = faces[i][j] - face.v.append(mesh.verts[index]) - if len(uvcoords) > 1: - uvidx = facesuv[i][j] - face.uv.append(uvcoords[uvidx]) - face.mode = 0 - #face.col = [Blender.NMesh.Col(r, g, b)]*4 # Random color - face.col = [Blender.NMesh.Col()]*4 + face.v.append(mesh.verts[faces[i][a]]) + face.v.append(mesh.verts[faces[i][b]]) + face.v.append(mesh.verts[faces[i][c]]) + b = c; c += 1 mesh.faces.append(face) - else: # Triangulate n-sided convex polygon. - a, b, c = 0, 1, 2 # Indices of first triangle. - for j in range(numfaceverts-2): # Number of triangles in polygon. - face = Blender.NMesh.Face() - face.v.append(mesh.verts[faces[i][a]]) - face.v.append(mesh.verts[faces[i][b]]) - face.v.append(mesh.verts[faces[i][c]]) - b = c; c += 1 - mesh.faces.append(face) - #face.smooth = 1 - -# ===================================== -# ==== Append Verts to Vertex List ==== -# ===================================== - def append_verts(mesh, verts, normals): - #print "Number of normals:", len(normals) - #print "Number of verts :", len(verts) - for i in range(len(verts)): - if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(verts), "Generating Verts") - x, y, z = verts[i] - mesh.verts.append(Blender.NMesh.Vert(x, y, z)) - if normals: - mesh.verts[i].no[0] = normals[i][0] - mesh.verts[i].no[1] = normals[i][1] - mesh.verts[i].no[2] = normals[i][2] - -# ============================= -# ==== Create Blender Mesh ==== -# ============================= - def create_mesh(verts, faces, objname, facesuv=[], uvcoords=[], normals=[]): - if normals: normal_flag = 0 - else: normal_flag = 1 - mesh = Blender.NMesh.GetRaw() - append_verts(mesh, verts, normals) - append_faces(mesh, faces, facesuv, uvcoords) - if not mod_flags.overwrite_mesh_name: - objname = versioned_name(objname) - Blender.NMesh.PutRaw(mesh, objname, normal_flag) # Name the Mesh - Blender.Object.GetSelected()[0].name=objname # Name the Object - Blender.Redraw() - -except ImportError: pass + #face.smooth = 1 -# ================================ -# ==== Increment Name Version ==== -# ================================ +# =================================== +# === Append Verts to Vertex List === +# =================================== +def append_verts(mesh, verts, normals): + #print "Number of normals:", len(normals) + #print "Number of verts :", len(verts) + for i in range(len(verts)): + if not i%100 and show_progress: Blender.Window.DrawProgressBar(float(i)/len(verts), "Generating Verts") + x, y, z = verts[i] + mesh.verts.append(Blender.NMesh.Vert(x, y, z)) + if normals: + mesh.verts[i].no[0] = normals[i][0] + mesh.verts[i].no[1] = normals[i][1] + mesh.verts[i].no[2] = normals[i][2] + +# =========================== +# === Create Blender Mesh === +# =========================== +def create_mesh(verts, faces, objname, facesuv=[], uvcoords=[], normals=[]): + if normals: normal_flag = 0 + else: normal_flag = 1 + mesh = Blender.NMesh.GetRaw() + append_verts(mesh, verts, normals) + append_faces(mesh, faces, facesuv, uvcoords) + if not overwrite_mesh_name: + objname = versioned_name(objname) + Blender.NMesh.PutRaw(mesh, objname, normal_flag) # Name the Mesh + Blender.Object.GetSelected()[0].name=objname # Name the Object + Blender.Redraw() + +# ============================== +# === Increment Name Version === +# ============================== def versioned_name(objname): existing_names = [] for object in Blender.Object.Get(): @@ -104,35 +109,40 @@ def versioned_name(objname): break return objname -# ============================= -# ==== Print Text In A Box ==== -# ============================= +# =========================== +# === Print Text In A Box === +# =========================== def print_boxed(text): lines = text.splitlines() maxlinelen = max(map(len, lines)) - print '+-' + '-'*maxlinelen + '-+' - for line in lines: print '| ' + line.ljust(maxlinelen) + ' |' - print '+-' + '-'*maxlinelen + '-+' - + if sys.platform[:3] == "win": + print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191) + for line in lines: + print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179) + print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217) + else: + print '+-' + '-'*maxlinelen + '-+' + for line in lines: print '| ' + line.ljust(maxlinelen) + ' |' + print '+-' + '-'*maxlinelen + '-+' print '\a\r', # beep when done -# ================================================= -# ==== Get Euler Angles From A Rotation Matrix ==== -# ================================================= -#def mat2euler(mat): -# angle_y = -math.asin(mat[0][2]) -# c = math.cos(angle_y) -# if math.fabs(c) > 0.005: -# angle_x = math.atan2(mat[1][2]/c, mat[2][2]/c) -# angle_z = math.atan2(mat[0][1]/c, mat[0][0]/c) -# else: -# angle_x = 0.0 -# angle_z = -math.atan2(mat[1][0], mat[1][1]) -# return (angle_x, angle_y, angle_z) - -# ============================ -# ==== Transpose A Matrix ==== -# ============================ +# =============================================== +# === Get euler angles from a rotation matrix === +# =============================================== +def mat2euler(mat): + angle_y = -math.asin(mat[0][2]) + c = math.cos(angle_y) + if math.fabs(c) > 0.005: + angle_x = math.atan2(mat[1][2]/c, mat[2][2]/c) + angle_z = math.atan2(mat[0][1]/c, mat[0][0]/c) + else: + angle_x = 0.0 + angle_z = -math.atan2(mat[1][0], mat[1][1]) + return (angle_x, angle_y, angle_z) + +# ========================== +# === Transpose A Matrix === +# ========================== def transpose(A): S = len(A) T = len(A[0]) @@ -142,37 +152,177 @@ def transpose(A): B[i][j] = A[j][i] return B -#def append_ntimes(Seq, N): -# Seq = reduce(operator.add, Seq) # Flatten once -# if N == 1: return Seq -# return append_ntimes(Seq, N-1) - - - -# print "mesh.has_col ", mesh.has_col -# print "mesh.hasVertexColours()", mesh.hasVertexColours() -# print "mesh.hasFaceUV() ", mesh.hasFaceUV() -# print "mesh.has_uvco ", mesh.has_uvco - -# # ============================= -# # ==== Create Blender Mesh ==== -# # ============================= -# def create_mesh_old(verts, faces, objname): -# mesh = Blender.NMesh.GetRaw() -# # === Vertex List === -# for i in range(len(verts)): -# x, y, z = verts[i] -# mesh.verts.append(Blender.NMesh.Vert(x, y ,z)) -# # === Face List === -# for i in range(len(faces)): -# face = Blender.NMesh.Face() -# for j in range(len(faces[i])): -# index = faces[i][j] -# face.v.append(mesh.verts[index]) -# mesh.faces.append(face) -# # === Name the Object === -# Blender.NMesh.PutRaw(mesh, objname) -# object = Blender.Object.GetSelected() -# object[0].name=objname -# Blender.Redraw() +# ======================= +# === Apply Transform === +# ======================= +def apply_transform(vertex, matrix): + x, y, z = vertex + xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2] + xcomponent = x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + xloc + ycomponent = x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + yloc + zcomponent = x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + zloc + vertex = [xcomponent, ycomponent, zcomponent] + return vertex + +# ========================= +# === Has Vertex Colors === +# ========================= +def has_vertex_colors(mesh): + # My replacement/workaround for hasVertexColours() + # The docs say: + # "Warning: If a mesh has both vertex colours and textured faces, + # this function will return False. This is due to the way Blender + # deals internally with the vertex colours array (if there are + # textured faces, it is copied to the textured face structure and + # the original array is freed/deleted)." + try: + return mesh.faces[0].col[0] + except: + return 0 + +# =========================== +# === Generate Edge Table === +# =========================== +def generate_edgetable(mesh): + edge_table = {} + numfaces = len(mesh.faces) + + for i in range(numfaces): + if not i%100 and show_progress: + Blender.Window.DrawProgressBar(float(i)/numfaces, "Generating Edge Table") + if len(mesh.faces[i].v) == 4: # Process Quadrilaterals + generate_entry_from_quad(mesh, i, edge_table) + elif len(mesh.faces[i].v) == 3: # Process Triangles + generate_entry_from_tri(mesh, i, edge_table) + else: # Skip This Face + print "Face #", i, "was skipped." + + # === Sort Edge_Table Keys & Add Edge Indices === + i = 0 + keys = edge_table.keys() + keys.sort() + for key in keys: + edge_table[key][6] = i + i += 1 + + # === Replace Tuples With Indices === + for key in keys: + for i in [2,3,4,5]: + if edge_table.has_key(edge_table[key][i]): + edge_table[key][i] = edge_table[edge_table[key][i]][6] + else: + keyrev = (edge_table[key][i][1], edge_table[key][i][0]) + edge_table[key][i] = edge_table[keyrev][6] + + return edge_table + +# ================================ +# === Generate Entry From Quad === +# ================================ +def generate_entry_from_quad(mesh, i, edge_table): + vertex4, vertex3, vertex2, vertex1 = mesh.faces[i].v + + if has_vertex_colors(mesh): + vcolor4, vcolor3, vcolor2, vcolor1 = mesh.faces[i].col + Acol = (vcolor1.r/255.0, vcolor1.g/255.0, vcolor1.b/255.0) + Bcol = (vcolor2.r/255.0, vcolor2.g/255.0, vcolor2.b/255.0) + Ccol = (vcolor3.r/255.0, vcolor3.g/255.0, vcolor3.b/255.0) + Dcol = (vcolor4.r/255.0, vcolor4.g/255.0, vcolor4.b/255.0) + + # === verts are upper case, edges are lower case === + A, B, C, D = vertex1.index, vertex2.index, vertex3.index, vertex4.index + a, b, c, d = (A, B), (B, C), (C, D), (D, A) + + if edge_table.has_key((B, A)): + edge_table[(B, A)][1] = i + edge_table[(B, A)][4] = d + edge_table[(B, A)][5] = b + if has_vertex_colors(mesh): edge_table[(B, A)][8] = Bcol + else: + if has_vertex_colors(mesh): + edge_table[(A, B)] = [i, None, d, b, None, None, None, Bcol, None] + else: + edge_table[(A, B)] = [i, None, d, b, None, None, None] + + if edge_table.has_key((C, B)): + edge_table[(C, B)][1] = i + edge_table[(C, B)][4] = a + edge_table[(C, B)][5] = c + if has_vertex_colors(mesh): edge_table[(C, B)][8] = Ccol + else: + if has_vertex_colors(mesh): + edge_table[(B, C)] = [i, None, a, c, None, None, None, Ccol, None] + else: + edge_table[(B, C)] = [i, None, a, c, None, None, None] + + if edge_table.has_key((D, C)): + edge_table[(D, C)][1] = i + edge_table[(D, C)][4] = b + edge_table[(D, C)][5] = d + if has_vertex_colors(mesh): edge_table[(D, C)][8] = Dcol + else: + if has_vertex_colors(mesh): + edge_table[(C, D)] = [i, None, b, d, None, None, None, Dcol, None] + else: + edge_table[(C, D)] = [i, None, b, d, None, None, None] + + if edge_table.has_key((A, D)): + edge_table[(A, D)][1] = i + edge_table[(A, D)][4] = c + edge_table[(A, D)][5] = a + if has_vertex_colors(mesh): edge_table[(A, D)][8] = Acol + else: + if has_vertex_colors(mesh): + edge_table[(D, A)] = [i, None, c, a, None, None, None, Acol, None] + else: + edge_table[(D, A)] = [i, None, c, a, None, None, None] + +# ==================================== +# === Generate Entry From Triangle === +# ==================================== +def generate_entry_from_tri(mesh, i, edge_table): + vertex3, vertex2, vertex1 = mesh.faces[i].v + + if has_vertex_colors(mesh): + vcolor3, vcolor2, vcolor1, _vcolor4_ = mesh.faces[i].col + Acol = (vcolor1.r/255.0, vcolor1.g/255.0, vcolor1.b/255.0) + Bcol = (vcolor2.r/255.0, vcolor2.g/255.0, vcolor2.b/255.0) + Ccol = (vcolor3.r/255.0, vcolor3.g/255.0, vcolor3.b/255.0) + + # === verts are upper case, edges are lower case === + A, B, C = vertex1.index, vertex2.index, vertex3.index + a, b, c = (A, B), (B, C), (C, A) + + if edge_table.has_key((B, A)): + edge_table[(B, A)][1] = i + edge_table[(B, A)][4] = c + edge_table[(B, A)][5] = b + if has_vertex_colors(mesh): edge_table[(B, A)][8] = Bcol + else: + if has_vertex_colors(mesh): + edge_table[(A, B)] = [i, None, c, b, None, None, None, Bcol, None] + else: + edge_table[(A, B)] = [i, None, c, b, None, None, None] + + if edge_table.has_key((C, B)): + edge_table[(C, B)][1] = i + edge_table[(C, B)][4] = a + edge_table[(C, B)][5] = c + if has_vertex_colors(mesh): edge_table[(C, B)][8] = Ccol + else: + if has_vertex_colors(mesh): + edge_table[(B, C)] = [i, None, a, c, None, None, None, Ccol, None] + else: + edge_table[(B, C)] = [i, None, a, c, None, None, None] + + if edge_table.has_key((A, C)): + edge_table[(A, C)][1] = i + edge_table[(A, C)][4] = b + edge_table[(A, C)][5] = a + if has_vertex_colors(mesh): edge_table[(A, C)][8] = Acol + else: + if has_vertex_colors(mesh): + edge_table[(C, A)] = [i, None, b, a, None, None, None, Acol, None] + else: + edge_table[(C, A)] = [i, None, b, a, None, None, None] diff --git a/release/scripts/nendo_export.py b/release/scripts/nendo_export.py new file mode 100644 index 00000000000..97796f03207 --- /dev/null +++ b/release/scripts/nendo_export.py @@ -0,0 +1,183 @@ +#!BPY + +""" +Name: 'Nendo...' +Blender: 232 +Group: 'Export' +Tooltip: 'Export selected mesh to Nendo File Format (*.ndo)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2001 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | September 25, 2001 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write Nendo File Format (*.nendo) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, time, sys, os + +# ============================== +# === Write Nendo 1.1 Format === +# ============================== +def write(filename): + start = time.clock() + + objects = Blender.Object.GetSelected() + objname = objects[0].name + meshname = objects[0].data.name + mesh = Blender.NMesh.GetRaw(meshname) + obj = Blender.Object.Get(objname) + + numedges = len(mesh.verts)+len(mesh.faces)-2 + maxedges = (2**16)-1 # Blender & Wings can read more edges + #maxedges = 32767 # Nendo can't + if numedges > maxedges: + message = objname + " can't be exported to Nendo format (too many edges)." + Blender.Draw.PupMenu("Nendo Export Error%t|"+message) + return + + edge_table = mod_meshtools.generate_edgetable(mesh) + + try: + edge_table = mod_meshtools.generate_edgetable(mesh) + assert len(edge_table) <= maxedges + except: + edge_table = {} + message = "Unable to generate Edge Table for the object named " + meshname + mod_meshtools.print_boxed(message) + Blender.Draw.PupMenu("Edge Table Error%t|"+message) + Blender.Window.DrawProgressBar(1.0, "") # clear progressbar + return + + file = open(filename, "wb") + write_header(file) + write_object_flags(file, objname) + write_edge_table(file, edge_table) + write_face_table(file, edge_table) + write_vert_table(file, edge_table, mesh) + write_texture(file) + file.close() + + Blender.Window.DrawProgressBar(1.0, "") # clear progressbar + print '\a\r', + end = time.clock() + seconds = " in %.2f %s" % (end-start, "seconds") + message = "Successfully exported " + os.path.basename(filename) + seconds + mod_meshtools.print_boxed(message) + +# ==================== +# === Write Header === +# ==================== +def write_header(file): + file.write("nendo 1.1") + file.write("\0\0") + file.write("\1") # numobjects + +# ========================== +# === Write Object Flags === +# ========================== +def write_object_flags(file, objname): + file.write("\1") # good flag + file.write(struct.pack(">H", len(objname))) + file.write(objname) + file.write("\1"*4) + data = struct.pack(">18f",0,0,0,1,1,1,1,1,1,1,1,1,0.2,0.2,0.2,1,100,1) + data = "<<<< Nendo Export Script for Blender -- (c) 2004 Anthony D'Agostino >>>>" + file.write(data) + +# ======================== +# === Write Edge Table === +# ======================== +def write_edge_table(file, edge_table): + "+--------------------------------------+" + "| Wings: Sv Ev | Lf Rf | Lp Ls | Rp Rs |" + "| Nendo: Ev Sv | Lf Rf | Ls Rs | Rp Lp |" + "+--------------------------------------+" + #$print "edge_table"; pprint.pprint(edge_table) + file.write(struct.pack(">H", len(edge_table))) + keys = edge_table.keys() + keys.sort() + for key in keys: + file.write(struct.pack(">2H", key[0], key[1])) # Ev Sv + file.write(struct.pack(">2H", edge_table[key][0], edge_table[key][1])) # Lf Rf + file.write(struct.pack(">2H", edge_table[key][3], edge_table[key][5])) # Ls Rs + file.write(struct.pack(">2H", edge_table[key][4], edge_table[key][2])) # Rp Lp + file.write(struct.pack(">1B", 0)) # Hard flag + try: + r1,g1,b1 = map(lambda x:x*255, edge_table[key][8]) + r2,g2,b2 = map(lambda x:x*255, edge_table[key][7]) + except: + r1,g1,b1 = map(lambda x:x*255, [0.9,0.8,0.7]) + r2,g2,b2 = r1,g1,b1 + file.write(struct.pack(">8B", r1,g1,b1,0,r2,g2,b2,0)) + +# ======================== +# === Write Face Table === +# ======================== +def write_face_table(file, edge_table): + face_table = build_face_table(edge_table) + #$print "face_table"; pprint.pprint(face_table) + file.write(struct.pack(">H", len(face_table))) + keys = face_table.keys() + keys.sort() + for key in keys: + file.write(struct.pack(">1H", face_table[key])) + +# ======================== +# === Write Vert Table === +# ======================== +def write_vert_table(file, edge_table, mesh): + vert_table = build_vert_table(edge_table) + #$print "vert_table"; pprint.pprint(vert_table) + file.write(struct.pack(">H", len(vert_table))) + keys = vert_table.keys() + keys.sort() + for key in keys: + vertex = mesh.verts[key].co + x,y,z = map(lambda x:x*10, vertex) # scale + idx = vert_table[key] + #$print "%i % f % f % f" % (idx, x, y, z) + file.write(struct.pack(">1H3f", idx, x, z, -y)) + +# ===================== +# === Write Texture === +# ===================== +def write_texture(file): + file.write("\0"*5) + +# ======================== +# === Build Vert Table === +# ======================== +def build_vert_table(edge_table): # For Nendo + vert_table = {} + for key in edge_table.keys(): + i = edge_table[key][6] + Sv = key[0] + Ev = key[1] + vert_table[Sv] = i + vert_table[Ev] = i + return vert_table + +# ======================== +# === Build Face Table === +# ======================== +def build_face_table(edge_table): # For Nendo + face_table = {} + for key in edge_table.keys(): + i = edge_table[key][6] + Lf = edge_table[key][0] + Rf = edge_table[key][1] + face_table[Lf] = i + face_table[Rf] = i + return face_table + +def fs_callback(filename): + if filename.find('.ndo', -4) <= 0: filename += '.ndo' + write(filename) + +Blender.Window.FileSelector(fs_callback, "Nendo Export") diff --git a/release/scripts/nendo_import.py b/release/scripts/nendo_import.py new file mode 100644 index 00000000000..d14d99d87ab --- /dev/null +++ b/release/scripts/nendo_import.py @@ -0,0 +1,205 @@ +#!BPY + +""" +Name: 'Nendo...' +Blender: 232 +Group: 'Import' +Tooltip: 'Import Nendo Object File Format (*.ndo)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2001 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | September 25, 2001 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write Nendo File Format (*.nendo) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, time, sys, os + +# ============================= +# === Read Nendo 1.x Format === +# ============================= +def read(filename): + start = time.clock() + file = open(filename, "rb") + version, numobjs = read_header(file) + + for object in range(numobjs): + good, = struct.unpack(">B", file.read(1)) + if not good: continue # an empty object + objname = read_object_flags(file) + edge_table = read_edge_table(file, version) + face_table = read_face_table(file) + vert_table = read_vert_table(file) + uv = read_uv(file) + verts = make_verts(vert_table) + faces = make_faces(edge_table) + mod_meshtools.create_mesh(verts, faces, objname) + + Blender.Window.DrawProgressBar(1.0, "Done") # clear progressbar + file.close() + end = time.clock() + seconds = " in %.2f %s" % (end-start, "seconds") + message = "Successfully imported " + os.path.basename(filename) + seconds + message += " (%s)" % version.title() + mod_meshtools.print_boxed(message) + +# ======================= +# === Read The Header === +# ======================= +def read_header(file): + version, = struct.unpack(">9s", file.read(9)) + misc, = struct.unpack(">H", file.read(2)) + numobjs, = struct.unpack(">B", file.read(1)) + if (version != "nendo 1.0") and (version != "nendo 1.1"): + mod_meshtools.print_boxed(file.name, "is not a Nendo file") + return + return version, numobjs + +# ========================= +# === Read Object Flags === +# ========================= +def read_object_flags(file): + namelen, = struct.unpack(">H", file.read(2)) + objname = file.read(namelen) + visible, = struct.unpack(">B", file.read(1)) + sensity, = struct.unpack(">B", file.read(1)) + other, = struct.unpack(">H", file.read(2)) # or 2 more flags? + misc = struct.unpack(">18f", file.read(72)) + return objname + +# ======================= +# === Read Edge Table === +# ======================= +def read_edge_table(file, version): + numedges, = struct.unpack(">H", file.read(2)) + edge_table = {} + for i in range(numedges): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/numedges, "Reading Edge Table") + edge = struct.unpack(">8H", file.read(16)) + if version == "nendo 1.1": + hard, = struct.unpack(">B", file.read(1)) # edge hardness flag + color = struct.unpack(">8B", file.read(8)) + edge_table[i] = edge + return edge_table + +# ======================= +# === Read Face Table === +# ======================= +def read_face_table(file): + numfaces, = struct.unpack(">H", file.read(2)) + face_table = {} + for i in range(numfaces): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Face Table") + face_table[i] = struct.unpack(">H", file.read(2))[0] + return face_table + +# ======================= +# === Read Vert Table === +# ======================= +def read_vert_table(file): + numverts, = struct.unpack(">H", file.read(2)) + vert_table = [] + for i in range(numverts): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Vertex Table") + w, x, y, z = struct.unpack(">H3f", file.read(14)) + vert_table.append((w,(x, y, z))) + return vert_table + +# ==================== +# === Read Texture === +# ==================== +def read_uv(file): + numuvs, = struct.unpack(">H", file.read(2)) + uvlist = struct.unpack(">"+`numuvs`+"H", file.read(numuvs*2)) + numfacesT, = struct.unpack(">H", file.read(2)) + facesT = struct.unpack(">"+`numfacesT`+"H", file.read(numfacesT*2)) + textureflag, = struct.unpack(">B", file.read(1)) + if textureflag: + xres, yres = struct.unpack(">2H", file.read(4)) + print "%ix%i" % (xres, yres) + pixel = 0 + while pixel < (xres*yres): + if not pixel%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(pixel)/xres*yres, "Reading Texture") + count, = struct.unpack(">B", file.read(1)) + rgb = file.read(3) + pixel = pixel+count + return numuvs + +# ================== +# === Make Verts === +# ================== +def make_verts(vert_table): + matrix = [ # Rotate 90*x and Scale 0.1 + [0.1, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.1, 0.0], + [0.0,-0.1, 0.0, 0.0], + [0.0, 0.0, 0.0, 1.0]] + verts = [] + for i in range(len(vert_table)): + vertex = vert_table[i][1] + vertex = mod_meshtools.apply_transform(vertex, matrix) + verts.append(vertex) + return verts + +# ======================= +# === Make Face Table === +# ======================= +def make_face_table(edge_table): # For Nendo + face_table = {} + for i in range(len(edge_table)): + Lf = edge_table[i][2] + Rf = edge_table[i][3] + face_table[Lf] = i + face_table[Rf] = i + return face_table + +# ======================= +# === Make Vert Table === +# ======================= +def make_vert_table(edge_table): # For Nendo + vert_table = {} + for i in range(len(edge_table)): + Sv = edge_table[i][1] + Ev = edge_table[i][0] + vert_table[Sv] = i + vert_table[Ev] = i + return vert_table + +# ================== +# === Make Faces === +# ================== +def make_faces(edge_table): # For Nendo + face_table = make_face_table(edge_table) + faces=[] + #for i in range(len(face_table)): + for i in face_table.keys(): # avoids a whole class of errors + face_verts = [] + current_edge = face_table[i] + while(1): + if i == edge_table[current_edge][3]: + next_edge = edge_table[current_edge][5] # Right successor edge + next_vert = edge_table[current_edge][1] + else: + next_edge = edge_table[current_edge][4] # Left successor edge + next_vert = edge_table[current_edge][0] + face_verts.append(next_vert) + current_edge = next_edge + if current_edge == face_table[i]: break + face_verts.reverse() # Flip all face normals + faces.append(face_verts) + return faces + +def fs_callback(filename): + read(filename) + +Blender.Window.FileSelector(fs_callback, "Nendo Import") diff --git a/release/scripts/obj_export.py b/release/scripts/obj_export.py new file mode 100644 index 00000000000..2fb84274c98 --- /dev/null +++ b/release/scripts/obj_export.py @@ -0,0 +1,161 @@ +#!BPY + +""" +Name: 'OBJ Wavefront' +Blender: 232 +Group: 'Export' +Tooltip: 'Save a Wavefront OBJ File' +""" + +# -------------------------------------------------------------------------- +# OBJ Export v0.9 by Campbell Barton (AKA Ideasman) +# -------------------------------------------------------------------------- +# ***** BEGIN GPL 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. +# +# 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. +# +# ***** END GPL LICENCE BLOCK ***** +# -------------------------------------------------------------------------- + +#================================================# +# Gets the world matrix of an object # +# by multiplying by parents mat's recursively # +# This only works in some simple situations, # +# needs work.... # +#================================================# +def getWorldMat(ob): + mat = ob.getMatrix() + p = ob.getParent() + if p != None: + mat = mat + getWorldMat(p) + return mat + +#==================# +# Apply Transform # +#==================# +def apply_transform(verts, matrix): + + x, y, z = verts + xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2] + xcomponent = x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + xloc + ycomponent = x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + yloc + zcomponent = x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + zloc + + return [xcomponent, ycomponent, zcomponent] + + +#=====================================# +# Apply Transform for vertex normals # +# ignore the translation # +#=====================================# +def apply_normal_transform(verts, matrix): + x, y, z = verts + xcomponent = x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + ycomponent = x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + zcomponent = x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + return Mathutils.Vector([xcomponent, ycomponent, zcomponent]) + +#====================================================# +# Return a 6 deciaml point floating point value # +# as a string that dosent have any python chars # +#====================================================# +def saneFloat(float): + #return '%(float)b' % vars() # 6 fp as house.hqx + return str('%f' % float) + ' ' + + +from Blender import * + +NULL_MAT = '(null)' + +def save_obj(filename): + + file = open(filename, "w") + + # Write Header + file.write('# Blender OBJ File: ' + Get('filename') + ' \n') + file.write('# www.blender.org\n') + + # Get all meshs + for ob in Object.Get(): + if ob.getType() == 'Mesh': + m = ob.getData() + if len(m.verts) > 0: # Make sure there is somthing to write. + + # Set the default mat + currentMatName = '' + + file.write('o ' + ob.getName() + '_' + m.name + '\n') # Write Object name + + # Dosent work properly, + matrix = getWorldMat(ob) + + # Vert + for v in m.verts: + # Transform the vert + vTx = apply_transform(v.co, matrix) + + file.write('v ') + file.write(saneFloat(vTx[0])) + file.write(saneFloat(vTx[1])) + file.write(saneFloat(vTx[2]) + '\n') + + # UV + for f in m.faces: + for uvIdx in range(len(f.v)): + file.write('vt ') + if f.uv: + file.write(saneFloat(f.uv[uvIdx][0])) + file.write(saneFloat(f.uv[uvIdx][1])) + else: + file.write('0.0 ') + file.write('0.0 ') + + file.write('0.0' + '\n') + + # NORMAL + for f in m.faces: + for v in f.v: + # Transform the normal + noTx = apply_normal_transform(v.no, matrix) + noTx.normalize() + file.write('vn ') + file.write(saneFloat(noTx[0])) + file.write(saneFloat(noTx[1])) + file.write(saneFloat(noTx[2]) + '\n') + + uvIdx = 0 + for f in m.faces: + # Check material and change if needed. + if len(m.materials) > f.mat: + if currentMatName != m.materials[f.mat].getName(): + currentMatName = m.materials[f.mat].getName() + file.write('usemtl ' + currentMatName + '\n') + + elif currentMatName != NULL_MAT: + currentMatName = NULL_MAT + file.write('usemtl ' + currentMatName + '\n') + + file.write('f ') + for v in f.v: + file.write( str(m.verts.index(v) +1) + '/') # Vert IDX + file.write( str(uvIdx +1) + '/') # UV IDX + file.write( str(uvIdx +1) + ' ') # NORMAL IDX + uvIdx+=1 + file.write('\n') + + file.close() + +Window.FileSelector(save_obj, 'SELECT OBJ FILE') diff --git a/release/scripts/obj_import.py b/release/scripts/obj_import.py new file mode 100644 index 00000000000..856b156deb5 --- /dev/null +++ b/release/scripts/obj_import.py @@ -0,0 +1,245 @@ +#!BPY + +""" +Name: 'OBJ Wavefront' +Blender: 232 +Group: 'Import' +Tooltip: 'Load a Wavefront OBJ File' + """ + +# -------------------------------------------------------------------------- +# OBJ Import v0.9 by Campbell Barton (AKA Ideasman) +# -------------------------------------------------------------------------- +# ***** BEGIN GPL 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. +# +# 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. +# +# ***** END GPL LICENCE BLOCK ***** +# -------------------------------------------------------------------------- + +WHITESPACE = [' ', '\n', '\r', '\t', '\f', '\v'] # used for the split function. +NULL_MAT = '(null)' # Name for mesh's that have no mat set. + +MATLIMIT = 16 + +#==============================================# +# Strips the slashes from the back of a string # +#==============================================# +def stripPath(path): + for CH in range(len(path), 0, -1): + if path[CH-1] == "/" or path[CH-1] == "\\": + path = path[CH:] + break + return path + +#====================================================# +# Strips the prefix off the name before writing # +#====================================================# +def stripName(name): # name is a string + prefixDelimiter = '.' + return name[ : name.find(prefixDelimiter) ] + +#================================================================# +# Replace module deps 'string' for join and split # # +# - Split splits a string into a list, and join does the reverse # +#================================================================# +def split(splitString, WHITESPACE): + splitList = [] + charIndex = 0 + while charIndex < len(splitString): + # Skip white space + while charIndex < len(splitString): + if splitString[charIndex] in WHITESPACE: + charIndex += 1 + else: + break + + # Gather text that is not white space and append to splitList + startWordCharIndex = charIndex + while charIndex < len(splitString): + if splitString[charIndex] in WHITESPACE: break + charIndex += 1 + + # Now we have the first and last chars we can append the word to the list + if charIndex != startWordCharIndex: + splitList.append(splitString[startWordCharIndex:charIndex]) + + return splitList + +#===============================# +# Join list items into a string # +#===============================# +def join(joinList): + joinedString = "" + for listItem in joinList: + joinedString = joinedString + ' ' + str(listItem) + + # Remove the first space + joinedString = joinedString[1:] + return joinedString + + +from Blender import * + +def load_obj(file): + # This gets a mat or creates one of the requested name if none exist. + def getMat(matName): + # Make a new mat + try: + return Material.Get(matName) + except: + return Material.New(matName) + + def applyMat(mesh, f, mat): + # Check weather the 16 mat limit has been met. + if len( mesh.materials ) >= MATLIMIT: + print 'Warning, max material limit reached, using an existing material' + return mesh, f + + mIdx = 0 + for m in mesh.materials: + if m.getName() == mat.getName(): + break + mIdx+=1 + + if mIdx == len(mesh.materials): + mesh.addMaterial(mat) + + f.mat = mIdx + return mesh, f + + # Get the file name with no path or .obj + fileName = stripName( stripPath(file) ) + + fileLines = open(file, 'r').readlines() + + mesh = NMesh.GetRaw() # new empty mesh + + objectName = 'mesh' # If we cant get one, use this + + uvMapList = [] # store tuple uv pairs here + + nullMat = getMat(NULL_MAT) + + currentMat = nullMat # Use this mat. + + # Main loop + lIdx = 0 + while lIdx < len(fileLines): + l = split(fileLines[lIdx], WHITESPACE) + + # Detect a line that will be idnored + if len(l) == 0: + pass + elif l[0] == '#' or len(l) == 0: + pass + # VERTEX + elif l[0] == 'v': + # This is a new vert, make a new mesh + mesh.verts.append( NMesh.Vert(eval(l[1]), eval(l[2]), eval(l[3]) ) ) + + elif l[0] == 'vn': + pass + + elif l[0] == 'vt': + # This is a new vert, make a new mesh + uvMapList.append( (eval(l[1]), eval(l[2])) ) + + elif l[0] == 'f': + + # Make a face with the correct material. + f = NMesh.Face() + mesh, f = applyMat(mesh, f, currentMat) + + # Set up vIdxLs : Verts + # Set up vtIdxLs : UV + vIdxLs = [] + vtIdxLs = [] + for v in l[1:]: + objVert = split( v, ['/'] ) + + # VERT INDEX + vIdxLs.append(eval(objVert[0]) -1) + # UV + if len(objVert) == 1: + vtIdxLs.append(eval(objVert[0]) -1) # Sticky UV coords + else: + vtIdxLs.append(eval(objVert[1]) -1) # Seperate UV coords + + # Quads only, we could import quads using the method below but it polite to import a quad as a quad.f + if len(vIdxLs) == 4: + f.v.append(mesh.verts[vIdxLs[0]]) + f.v.append(mesh.verts[vIdxLs[1]]) + f.v.append(mesh.verts[vIdxLs[2]]) + f.v.append(mesh.verts[vIdxLs[3]]) + # UV MAPPING + if uvMapList: + if vtIdxLs[0] < len(uvMapList): + f.uv.append( uvMapList[ vtIdxLs[0] ] ) + if vtIdxLs[1] < len(uvMapList): + f.uv.append( uvMapList[ vtIdxLs[1] ] ) + if vtIdxLs[2] < len(uvMapList): + f.uv.append( uvMapList[ vtIdxLs[2] ] ) + if vtIdxLs[3] < len(uvMapList): + f.uv.append( uvMapList[ vtIdxLs[3] ] ) + mesh.faces.append(f) # move the face onto the mesh + + elif len(vIdxLs) >= 3: # This handles tri's and fans + for i in range(len(vIdxLs)-2): + f = NMesh.Face() + mesh, f = applyMat(mesh, f, currentMat) + f.v.append(mesh.verts[vIdxLs[0]]) + f.v.append(mesh.verts[vIdxLs[i+1]]) + f.v.append(mesh.verts[vIdxLs[i+2]]) + # UV MAPPING + if uvMapList: + if vtIdxLs[0] < len(uvMapList): + f.uv.append( uvMapList[ vtIdxLs[0] ] ) + if vtIdxLs[1] < len(uvMapList): + f.uv.append( uvMapList[ vtIdxLs[i+1] ] ) + if vtIdxLs[2] < len(uvMapList): + f.uv.append( uvMapList[ vtIdxLs[i+2] ] ) + + mesh.faces.append(f) # move the face onto the mesh + + # is o the only vert/face delimeter? + # if not we could be screwed. + elif l[0] == 'o': + # Make sure the objects is worth puttong + if len(mesh.verts) > 0: + NMesh.PutRaw(mesh, fileName + '_' + objectName) + # Make new mesh + mesh = NMesh.GetRaw() + + # New mesh name + objectName = join(l[1:]) # Use join in case of spaces + + # New texture list + uvMapList = [] + + elif l[0] == 'usemtl': + if l[1] == '(null)': + currentMat = NULL_MAT + else: + currentMat = getMat(join(l[1:])) # Use join in case of spaces + + lIdx+=1 + + # We need to do this to put the last object. + # All other objects will be put alredy + if len(mesh.verts) > 0: + NMesh.PutRaw(mesh, fileName + '_' + objectName) + +Window.FileSelector(load_obj, 'SELECT OBJ FILE') diff --git a/release/scripts/off_export.py b/release/scripts/off_export.py index 9648c1c3271..de843561e4c 100644 --- a/release/scripts/off_export.py +++ b/release/scripts/off_export.py @@ -9,8 +9,8 @@ Tooltip: 'Export selected mesh to Object File Format (*.off)' # +---------------------------------------------------------+ # | Copyright (c) 2002 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | February 3, 2001 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | @@ -18,9 +18,8 @@ Tooltip: 'Export selected mesh to Object File Format (*.off)' # | Read and write Object File Format (*.off) | # +---------------------------------------------------------+ -import Blender +import Blender, mod_meshtools #import time -import mod_flags, mod_meshtools # ============================== # ====== Write OFF Format ====== @@ -42,14 +41,14 @@ def write(filename): # === Vertex List === for i in range(len(mesh.verts)): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts") x, y, z = mesh.verts[i].co file.write("%f %f %f\n" % (x, y, z)) # === Face List === for i in range(len(mesh.faces)): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces") file.write(`len(mesh.faces[i].v)`+' ') mesh.faces[i].v.reverse() diff --git a/release/scripts/off_import.py b/release/scripts/off_import.py index 9f7fd5eb9f7..44c5bf6ff05 100644 --- a/release/scripts/off_import.py +++ b/release/scripts/off_import.py @@ -9,8 +9,8 @@ Tooltip: 'Import Object File Format (*.off)' # +---------------------------------------------------------+ # | Copyright (c) 2002 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | February 3, 2001 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | @@ -18,9 +18,8 @@ Tooltip: 'Import Object File Format (*.off)' # | Read and write Object File Format (*.off) | # +---------------------------------------------------------+ -import Blender +import Blender, mod_meshtools #import time -import mod_flags, mod_meshtools # ============================= # ====== Read OFF Format ====== @@ -40,7 +39,7 @@ def read(filename): # === Vertex List === for i in range(numverts): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts") x, y, z = file.readline().split() x, y, z = float(x), float(y), float(z) @@ -48,7 +47,7 @@ def read(filename): # === Face List === for i in range(numfaces): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces") line = file.readline().split() numfaceverts = len(line)-1 diff --git a/release/scripts/radiosity_export.py b/release/scripts/radiosity_export.py index f87f8a1ef19..34c913dc1ef 100644 --- a/release/scripts/radiosity_export.py +++ b/release/scripts/radiosity_export.py @@ -9,8 +9,8 @@ Tooltip: 'Export selected mesh (with vertex colors) to Radiosity File Format (*. # +---------------------------------------------------------+ # | Copyright (c) 2002 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | April 11, 2002 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | @@ -18,14 +18,15 @@ Tooltip: 'Export selected mesh (with vertex colors) to Radiosity File Format (*. # | Read and write Radiosity File Format (*.radio) | # +---------------------------------------------------------+ -import Blender +import Blender, mod_meshtools #import time -import mod_flags, mod_meshtools + try: import struct except: msg = "Error: you need a full Python install to run this script." mod_meshtools.print_boxed(msg) + Blender.Draw.PupMenu("ERROR%t|"+msg) # ================================ # ====== Write Radio Format ====== @@ -40,10 +41,11 @@ def write(filename): mesh = Blender.NMesh.GetRaw(meshname) obj = Blender.Object.Get(objname) - if not mesh.hasVertexColours(): - message = "Please assign vertex colors before exporting.\n" + if not mod_meshtools.has_vertex_colors(mesh): + message = "Please assign vertex colors before exporting. \n" message += objname + " object was not saved." mod_meshtools.print_boxed(message) + Blender.Draw.PupMenu("ERROR%t|"+message) return # === Object Name === @@ -53,7 +55,7 @@ def write(filename): # === Vertex List === file.write(struct.pack("<l", len(mesh.verts))) for i in range(len(mesh.verts)): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts") x, y, z = mesh.verts[i].co @@ -62,7 +64,7 @@ def write(filename): # === Face List === file.write(struct.pack("<l", len(mesh.faces))) for i in range(len(mesh.faces)): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces") file.write(struct.pack("<b", len(mesh.faces[i].v))) diff --git a/release/scripts/radiosity_import.py b/release/scripts/radiosity_import.py index d2e784b3ed4..46705855285 100644 --- a/release/scripts/radiosity_import.py +++ b/release/scripts/radiosity_import.py @@ -9,8 +9,8 @@ Tooltip: 'Import Radiosity File Format (*.radio) with vertex colors' # +---------------------------------------------------------+ # | Copyright (c) 2002 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | April 11, 2002 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | @@ -18,14 +18,15 @@ Tooltip: 'Import Radiosity File Format (*.radio) with vertex colors' # | Read and write Radiosity File Format (*.radio) | # +---------------------------------------------------------+ -import Blender +import Blender, mod_meshtools #import time -import mod_flags, mod_meshtools + try: import struct except: msg = "Error: you need a full Python install to run this script." mod_meshtools.print_boxed(msg) + Blender.Draw.PupMenu("ERROR%t|"+msg) # =============================== # ====== Read Radio Format ====== @@ -34,7 +35,7 @@ def read(filename): #start = time.clock() file = open(filename, "rb") mesh = Blender.NMesh.GetRaw() - mesh.addMaterial(Blender.Material.New()) + #mesh.addMaterial(Blender.Material.New()) # === Object Name === namelen, = struct.unpack("<h", file.read(2)) @@ -43,7 +44,7 @@ def read(filename): # === Vertex List === numverts, = struct.unpack("<l", file.read(4)) for i in range(numverts): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts") x, y, z = struct.unpack("<fff", file.read(12)) mesh.verts.append(Blender.NMesh.Vert(x, y, z)) @@ -51,7 +52,7 @@ def read(filename): # === Face List === numfaces, = struct.unpack("<l", file.read(4)) for i in range(numfaces): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces") face = Blender.NMesh.Face() diff --git a/release/scripts/raw_export.py b/release/scripts/raw_export.py index 809f6e2354e..9c2407c41a7 100644 --- a/release/scripts/raw_export.py +++ b/release/scripts/raw_export.py @@ -9,8 +9,8 @@ Tooltip: 'Export selected mesh to Raw Triangle Format (*.raw)' # +---------------------------------------------------------+ # | Copyright (c) 2002 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | April 28, 2002 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | @@ -18,13 +18,13 @@ Tooltip: 'Export selected mesh to Raw Triangle Format (*.raw)' # | Read and write RAW Triangle File Format (*.raw) | # +---------------------------------------------------------+ -import Blender, sys +import Blender, mod_meshtools +import sys #import time -import mod_flags, mod_meshtools -# =================================== -# ==== Write RAW Triangle Format ==== -# =================================== +# ================================= +# === Write RAW Triangle Format === +# ================================= def write(filename): #start = time.clock() file = open(filename, "wb") diff --git a/release/scripts/raw_import.py b/release/scripts/raw_import.py index c080d028e3d..f1b6cc511e4 100644 --- a/release/scripts/raw_import.py +++ b/release/scripts/raw_import.py @@ -9,8 +9,8 @@ Tooltip: 'Import Raw Triangle File Format (*.raw)' # +---------------------------------------------------------+ # | Copyright (c) 2002 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | April 28, 2002 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | @@ -18,13 +18,12 @@ Tooltip: 'Import Raw Triangle File Format (*.raw)' # | Read and write RAW Triangle File Format (*.raw) | # +---------------------------------------------------------+ -import Blender +import Blender, mod_meshtools #import time -import mod_flags, mod_meshtools -# ================================== -# ==== Read RAW Triangle Format ==== -# ================================== +# ================================ +# === Read RAW Triangle Format === +# ================================ def read(filename): #start = time.clock() file = open(filename, "rb") diff --git a/release/scripts/rvk1_torvk2.py b/release/scripts/rvk1_torvk2.py new file mode 100644 index 00000000000..efe6c9a9559 --- /dev/null +++ b/release/scripts/rvk1_torvk2.py @@ -0,0 +1,108 @@ +#!BPY + +""" Registration info for Blender menus: <- these words are ignored +Name: 'Rvk1 to Rvk2' +Blender: 232 +Group: 'Animation' +Tip: 'Copy deform data (not surf. subdiv) of active obj to rvk of the 2nd selected obj.' +""" + +#---------------------------------------------- +# jm soler (c) 05/2004 : 'Rvk1toRvk2' release under blender artistic licence +#---------------------------------------------- +# Blender Artistic License +# http://download.blender.org/documentation/html/x21254.html +#---------------------------------------------------- +# Copy the rvk (1, or armature, lattice, or +# any mesh deformation except surface +# sbdivision) of the active object to rvk (2) of +# the second selected object. Create rvk or modify +# absolute key if needed. +#---------------------------------------------- +# official Page : +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_rvk1versrvk2.htm +# download the script : +# http://jmsoler.free.fr/util/blenderfile/py/rvk1_torvk2.py +# Communicate upon problems or errors: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#---------------------------------------------- +# Page officielle : +# http://jmsoler.free.fr/util/blenderfile/py/rvk1_torvk2.py +# Communiquer les problemes et erreurs sur: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#--------------------------------------------- +# changelog : +# - a test on mesh parity between getraw and getrawfromobject +# when there is active subsurf division. +# - can copy, or not, vertex groups from the original mesh. +#--------------------------------------------- + +import Blender +from Blender import NMesh,Draw,Object + +def rvk2rvk(): + try: + SUBMODIF=0 + RVK2=Object.GetSelected()[0] + RVK1=Object.GetSelected()[1] + + FRAME=Blender.Get('curframe') + + DATA2=RVK2.getData() + + if DATA2.getMode() & NMesh.Modes['SUBSURF'] : + SUBSURF2=DATA2.getSubDivLevels() + if SUBSURF2[0]!=0: + name = "The active object has a subsurf level different from 0 ... %t| Let script do the the modification for you ? %x1| you prefer do it yourself ? %x2 " + result = Draw.PupMenu(name) + if result==1: + DATA2.mode=DATA2.mode-NMesh.Modes['SUBSURF'] + SUBMODIF=1 + DATA2.update() + RVK2.makeDisplayList() + Blender.Redraw() + else: + return + + RVK2NAME=Object.GetSelected()[0].getName() + mesh=RVK1.getData() + meshrvk2=NMesh.GetRawFromObject(RVK2NAME) + + name = "Do you want to replace or add vertex groups ? %t| YES %x1| NO ? %x2 " + result = Draw.PupMenu(name) + + if result==1: + GROUPNAME1=mesh.getVertGroupNames() + if len(GROUPNAME1)!=0: + for GROUP1 in GROUPNAME1: + mesh.removeVertGroup(GROUP1) + + GROUPNAME2=DATA2.getVertGroupNames() + if len(GROUPNAME2)!=0: + for GROUP2 in GROUPNAME2: + mesh.addVertGroup(GROUP2) + mesh.assignVertsToGroup(GROUP2,DATA2.getVertsFromGroup(GROUP2),1.0,'replace') + + for v in meshrvk2.verts: + i= meshrvk2.verts.index(v) + v1=mesh.verts[i] + for n in range(len(v.co)): + v1.co[n]=v.co[n] + + mesh.update() + mesh.insertKey(FRAME,'relative') + mesh.update() + RVK1.makeDisplayList() + + if SUBMODIF==1: + DATA2.mode=DATA2.mode+NMesh.Modes['SUBSURF'] + SUBMODIF=0 + DATA2.update() + RVK2.makeDisplayList() + + Blender.Redraw() + except: + print 'problem : not object selected or not mesh' + + +rvk2rvk() diff --git a/release/scripts/slp_import.py b/release/scripts/slp_import.py new file mode 100644 index 00000000000..a066e333445 --- /dev/null +++ b/release/scripts/slp_import.py @@ -0,0 +1,76 @@ +#!BPY + +""" +Name: 'SLP (Pro Engineer)...' +Blender: 232 +Group: 'Import' +Tooltip: 'Import SLP (Pro Engineer) File Format (*.raw)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2004 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | May 3, 2004 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write SLP Triangle File Format (*.slp) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +#import time + +# ================================ +# === Read SLP Triangle Format === +# ================================ +def read(filename): + #start = time.clock() + file = open(filename, "rb") + + raw = [] + for line in file.readlines(): + data = line.split() + if data[0] == "vertex": + vert = map(float, data[1:]) + raw.append(vert) + + tri = [] + for i in range(0, len(raw), 3): + tri.append(raw[i] + raw[i+1] + raw[i+2]) + + #$import pprint; pprint.pprint(tri) + + # Collect data from RAW format + faces = [] + for line in tri: + f1, f2, f3, f4, f5, f6, f7, f8, f9 = line + faces.append([(f1, f2, f3), (f4, f5, f6), (f7, f8, f9)]) + + # Generate verts and faces lists, without duplicates + verts = [] + coords = {} + index = 0 + for i in range(len(faces)): + for j in range(len(faces[i])): + vertex = faces[i][j] + if not coords.has_key(vertex): + coords[vertex] = index + index += 1 + verts.append(vertex) + faces[i][j] = coords[vertex] + + objname = Blender.sys.splitext(Blender.sys.basename(filename))[0] + + mod_meshtools.create_mesh(verts, faces, objname) + Blender.Window.DrawProgressBar(1.0, '') # clear progressbar + file.close() + #end = time.clock() + #seconds = " in %.2f %s" % (end-start, "seconds") + message = "Successfully imported " + Blender.sys.basename(filename)# + seconds + mod_meshtools.print_boxed(message) + +def fs_callback(filename): + read(filename) + +Blender.Window.FileSelector(fs_callback, "SLP Import") diff --git a/release/scripts/truespace_export.py b/release/scripts/truespace_export.py new file mode 100644 index 00000000000..8013278e528 --- /dev/null +++ b/release/scripts/truespace_export.py @@ -0,0 +1,265 @@ +#!BPY + +""" +Name: 'TrueSpace...' +Blender: 232 +Group: 'Export' +Tooltip: 'Export selected meshes to trueSpace File Format (*.cob)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2001 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | June 12, 2001 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write Caligari trueSpace File Format (*.cob) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, os, cStringIO, time + +# ============================== +# === Write trueSpace Format === +# ============================== +def write(filename): + start = time.clock() + file = open(filename, "wb") + objects = Blender.Object.GetSelected() + + write_header(file) + + G,P,V,U,M = 1000,2000,3000,4000,5000 + for object in objects: + objname = object.name + meshname = object.data.name + mesh = Blender.NMesh.GetRaw(meshname) + obj = Blender.Object.Get(objname) + if not mesh: continue + + grou = generate_grou('Group ' + `objects.index(object)+1`) + polh = generate_polh(objname, obj, mesh) + if mod_meshtools.has_vertex_colors(mesh): vcol = generate_vcol(mesh) + unit = generate_unit() + mat1 = generate_mat1(mesh) + + if objects.index(object) == 0: X = 0 + + write_chunk(file, "Grou", 0, 1, G, X, grou) + write_chunk(file, "PolH", 0, 4, P, G, polh) + if mod_meshtools.has_vertex_colors(mesh) and vcol: + write_chunk(file, "VCol", 1, 0, V, P, vcol) + write_chunk(file, "Unit", 0, 1, U, P, unit) + write_chunk(file, "Mat1", 0, 5, M, P, mat1) + + X = G + G,P,V,U,M = map(lambda x: x+1, [G,P,V,U,M]) + + write_chunk(file, "END ", 1, 0, 0, 0, '') # End Of File Chunk + + Blender.Window.DrawProgressBar(1.0, '') # clear progressbar + file.close() + end = time.clock() + seconds = " in %.2f %s" % (end-start, "seconds") + message = "Successfully exported " + os.path.basename(filename) + seconds + mod_meshtools.print_boxed(message) + +# ============================= +# === Write COB File Header === +# ============================= +def write_header(file): + file.write("Caligari V00.01BLH"+" "*13+"\n") + +# =================== +# === Write Chunk === +# =================== +def write_chunk(file, name, major, minor, chunk_id, parent_id, data): + file.write(name) + file.write(struct.pack("<2h", major, minor)) + file.write(struct.pack("<2l", chunk_id, parent_id)) + file.write(struct.pack("<1l", len(data))) + file.write(data) + +# ============================================ +# === Generate PolH (Polygonal Data) Chunk === +# ============================================ +def generate_polh(objname, obj, mesh): + data = cStringIO.StringIO() + write_ObjectName(data, objname) + write_LocalAxes(data, obj) + write_CurrentPosition(data, obj) + write_VertexList(data, mesh) + uvcoords = write_UVCoordsList(data, mesh) + write_FaceList(data, mesh, uvcoords) + return data.getvalue() + +# === Write Object Name === +def write_ObjectName(data, objname): + data.write(struct.pack("<h", 0)) # dupecount + data.write(struct.pack("<h", len(objname))) + data.write(objname) + +# === Write Local Axes === +def write_LocalAxes(data, obj): + data.write(struct.pack("<fff", obj.mat[3][0], obj.mat[3][1], obj.mat[3][2])) + data.write(struct.pack("<fff", obj.mat[0][0]/obj.SizeX, obj.mat[1][0]/obj.SizeX, obj.mat[2][0]/obj.SizeX)) + data.write(struct.pack("<fff", obj.mat[0][1]/obj.SizeY, obj.mat[1][1]/obj.SizeY, obj.mat[2][1]/obj.SizeY)) + data.write(struct.pack("<fff", obj.mat[0][2]/obj.SizeZ, obj.mat[1][2]/obj.SizeZ, obj.mat[2][2]/obj.SizeZ)) + +# === Write Current Position === +def write_CurrentPosition(data, obj): + data.write(struct.pack("<ffff", obj.mat[0][0], obj.mat[0][1], obj.mat[0][2], obj.mat[3][0])) + data.write(struct.pack("<ffff", obj.mat[1][0], obj.mat[1][1], obj.mat[1][2], obj.mat[3][1])) + data.write(struct.pack("<ffff", obj.mat[2][0], obj.mat[2][1], obj.mat[2][2], obj.mat[3][2])) + +# === Write Vertex List === +def write_VertexList(data, mesh): + data.write(struct.pack("<l", len(mesh.verts))) + for i in range(len(mesh.verts)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts") + x, y, z = mesh.verts[i].co + data.write(struct.pack("<fff", -y, x, z)) + +# === Write UV Vertex List === +def write_UVCoordsList(data, mesh): + if not mesh.hasFaceUV(): + data.write(struct.pack("<l", 1)) + data.write(struct.pack("<2f", 0,0)) + return {(0,0): 0} + # === Default UV Coords (one image per face) === + # data.write(struct.pack("<l", 4)) + # data.write(struct.pack("<8f", 0,0, 0,1, 1,1, 1,0)) + # return {(0,0): 0, (0,1): 1, (1,1): 2, (1,0): 3} + # === Default UV Coords (one image per face) === + + # === collect, remove duplicates, add indices, and write the uv list === + uvdata = cStringIO.StringIO() + uvcoords = {} + uvidx = 0 + for i in range(len(mesh.faces)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing UV Coords") + numfaceverts = len(mesh.faces[i].v) + for j in range(numfaceverts-1, -1, -1): # Reverse order + u,v = mesh.faces[i].uv[j] + if not uvcoords.has_key((u,v)): + uvcoords[(u,v)] = uvidx + uvidx += 1 + uvdata.write(struct.pack("<ff", u,v)) + uvdata = uvdata.getvalue() + + numuvcoords = len(uvdata)/8 + data.write(struct.pack("<l", numuvcoords)) + data.write(uvdata) + #print "Number of uvcoords:", numuvcoords, '=', len(uvcoords) + return uvcoords + +# === Write Face List === +def write_FaceList(data, mesh, uvcoords): + data.write(struct.pack("<l", len(mesh.faces))) + for i in range(len(mesh.faces)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces") + numfaceverts = len(mesh.faces[i].v) + data.write(struct.pack("<B", 0x10)) # Cull Back Faces Flag + data.write(struct.pack("<h", numfaceverts)) + data.write(struct.pack("<h", 0)) # Material Index + for j in range(numfaceverts-1, -1, -1): # Reverse order + index = mesh.faces[i].v[j].index + if mesh.hasFaceUV(): + uv = mesh.faces[i].uv[j] + uvidx = uvcoords[uv] + else: + uvidx = 0 + data.write(struct.pack("<ll", index, uvidx)) + +# =========================================== +# === Generate VCol (Vertex Colors) Chunk === +# =========================================== +def generate_vcol(mesh): + data = cStringIO.StringIO() + data.write(struct.pack("<l", len(mesh.faces))) + uniquecolors = {} + unique_alpha = {} + for i in range(len(mesh.faces)): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Vertex Colors") + numfaceverts = len(mesh.faces[i].v) + data.write(struct.pack("<ll", i, numfaceverts)) + for j in range(numfaceverts-1, -1, -1): # Reverse order + r = mesh.faces[i].col[j].r + g = mesh.faces[i].col[j].g + b = mesh.faces[i].col[j].b + a = 100 # 100 is opaque in ts + uniquecolors[(r,g,b)] = None + unique_alpha[mesh.faces[i].col[j].a] = None + data.write(struct.pack("<BBBB", r,g,b,a)) + + #print "uniquecolors:", uniquecolors.keys() + #print "unique_alpha:", unique_alpha.keys() + if len(uniquecolors) == 1: + return None + else: + return data.getvalue() + +# ================================== +# === Generate Unit (Size) Chunk === +# ================================== +def generate_unit(): + data = cStringIO.StringIO() + data.write(struct.pack("<h", 2)) + return data.getvalue() + +# ====================================== +# === Generate Mat1 (Material) Chunk === +# ====================================== +def generate_mat1(mesh): + data = cStringIO.StringIO() + data.write(struct.pack("<h", 0)) + data.write(struct.pack("<ccB", "p", "a", 0)) + data.write(struct.pack("<fff", 1.0, 1.0, 1.0)) # rgb (0.0 - 1.0) + data.write(struct.pack("<fffff", 1, 1, 0, 0, 1)) + if mesh.hasFaceUV(): + tex_mapname = r"c:\image\maps\one-dot.tga" + data.write("t:") + data.write(struct.pack("<B", 0x00)) + data.write(struct.pack("<h", len(tex_mapname))) + data.write(tex_mapname) + data.write(struct.pack("<4f", 0,0, 1,1)) + return data.getvalue() + +# ============================ +# === Generate Group Chunk === +# ============================ +def generate_grou(name): + data = cStringIO.StringIO() + write_ObjectName(data, name) + data.write(struct.pack("<12f", 0,0,0, 1,0,0, 0,1,0, 0,0,1)) + data.write(struct.pack("<12f", 1,0,0,0, 0,1,0,0, 0,0,1,0)) + return data.getvalue() + +def fs_callback(filename): + if filename.find('.cob', -4) <= 0: filename += '.cob' + write(filename) + +Blender.Window.FileSelector(fs_callback, "COB Export") + +# === Matrix Differences between Blender & trueSpace === +# +# For the 'Local Axes' values: +# The x, y, and z-axis represent a simple rotation matrix. +# This is equivalent to Blender's object matrix before it was +# combined with the object's scaling matrix. Dividing each value +# by the appropriate scaling factor (and transposing at the same +# time) produces the original rotation matrix. +# +# For the 'Current Position' values: +# This is equivalent to Blender's object matrix except that the +# last row is omitted and the xyz location is used in the last +# column. Binary format uses a 4x3 matrix, ascii format uses a 4x4 +# matrix. +# +# For Cameras: The matrix is a little confusing. diff --git a/release/scripts/truespace_import.py b/release/scripts/truespace_import.py new file mode 100644 index 00000000000..2b4f393d81f --- /dev/null +++ b/release/scripts/truespace_import.py @@ -0,0 +1,229 @@ +#!BPY + +""" +Name: 'TrueSpace...' +Blender: 232 +Group: 'Import' +Tooltip: 'Import trueSpace Object File Format (*.cob)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2001 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | June 12, 2001 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write Caligari trueSpace File Format (*.cob) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, chunk, os, cStringIO, time + +# ======================= +# === COB Chunk Class === +# ======================= +class CobChunk(chunk.Chunk): + def __init__(self, file, align = 0, bigendian = 0, inclheader = 0): #$ COB + self.closed = 0 + self.align = align # whether to align to word (2-byte) boundaries + if bigendian: + strflag = '>' + else: + strflag = '<' + self.file = file + self.chunkname = file.read(4) + if len(self.chunkname) < 4: + raise EOFError + self.major_ver, = struct.unpack(strflag+'h', file.read(2)) #$ COB + self.minor_ver, = struct.unpack(strflag+'h', file.read(2)) #$ COB + self.chunk_id, = struct.unpack(strflag+'l', file.read(4)) #$ COB + self.parent_id, = struct.unpack(strflag+'l', file.read(4)) #$ COB + try: + self.chunksize = struct.unpack(strflag+'l', file.read(4))[0] + except struct.error: + raise EOFError + if inclheader: + self.chunksize = self.chunksize - 20 #$ COB + self.size_read = 0 + try: + self.offset = self.file.tell() + except: + self.seekable = 0 + else: + self.seekable = 1 + +# ============================ +# === Read COB File Header === +# ============================ +def read_header(file): + magic, = struct.unpack("<9s", file.read(9)) + version, = struct.unpack("<6s", file.read(6)) + format, = struct.unpack("<1c", file.read(1)) + endian, = struct.unpack("<2s", file.read(2)) + misc, = struct.unpack("13s", file.read(13)) + newline, = struct.unpack("<1B", file.read(1)) + return format + +# ======================================== +# === Read PolH (Polygonal Data) Chunk === +# ======================================== +def read_polh(chunk): + data = cStringIO.StringIO(chunk.read()) + oname = read_ObjectName(data) + local = read_LocalAxes(data) + crpos = read_CurrentPosition(data) + verts = read_VertexList(data) + uvcoords = read_UVCoords(data) + faces, facesuv = read_FaceList(data, chunk) + return verts, faces, oname, facesuv, uvcoords + +# === Read Object Name === +def read_ObjectName(data): + dupecount, namelen = struct.unpack("<hh", data.read(4)) + objname = data.read(namelen) + if objname == '': objname = 'NoName' + if dupecount > 0: objname = objname + ', ' + `dupecount` + return objname + +# === Read Local Axes === +def read_LocalAxes(data): + location = struct.unpack("<fff", data.read(12)) + rotation_matrix=[] + for i in range(3): + row = struct.unpack("<fff", data.read(12)) + #print "% f % f % f" % row + rotation_matrix.append(list(row)) + #print + rotation_matrix = mod_meshtools.transpose(rotation_matrix) + +# === Read Current Position === +def read_CurrentPosition(data): + transformation_matrix=[] + for i in range(3): + row = struct.unpack("<ffff", data.read(16)) + #print "% f % f % f % f" % row + transformation_matrix.append(list(row)) + #print + +# === Read Vertex List === +def read_VertexList(data): + verts = [] + numverts, = struct.unpack("<l", data.read(4)) + for i in range(numverts): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts") + x, y, z = struct.unpack("<fff", data.read(12)) + verts.append((y, -x, z)) + return verts + +# === Read UV Vertex List === +def read_UVCoords(data): + uvcoords = [] + numuvcoords, = struct.unpack("<l", data.read(4)) + for i in range(numuvcoords): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/numuvcoords, "Reading UV Coords") + uv = struct.unpack("<ff", data.read(8)) + uvcoords.append(uv) + + #print "num uvcoords:", len(uvcoords) + #for i in range(len(uvcoords)): print "%.4f, %.4f" % uvcoords[i] + return uvcoords + +# === Read Face List === +def read_FaceList(data, chunk): + faces = [] ; facesuv = [] + numfaces, = struct.unpack("<l", data.read(4)) + for i in range(numfaces): + if not i%100 and mod_meshtools.show_progress: + Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces") + + face_flags, numfaceverts = struct.unpack("<Bh", data.read(3)) + + if (face_flags & 0x08) == 0x08: + print "face #" + `i-1` + " contains a hole." + pass + else: + data.read(2) # Material Index + + facev = [] ; faceuv = [] + for j in range(numfaceverts): + index, uvidx = struct.unpack("<ll", data.read(8)) + facev.append(index); faceuv.append(uvidx) + facev.reverse() ; faceuv.reverse() + faces.append(facev) ; facesuv.append(faceuv) + + if chunk.minor_ver == 6: + DrawFlags, RadiosityQuality = struct.unpack("<lh", data.read(6)) + if chunk.minor_ver == 8: + DrawFlags, = struct.unpack("<l", data.read(4)) + + return faces , facesuv + +# ============================= +# === Read trueSpace Format === +# ============================= +def read(filename): + start = time.clock() + file = open(filename, "rb") + + # === COB header === + if read_header(file) == 'A': + print "Can't read ASCII format" + return + + while 1: + try: + cobchunk = CobChunk(file) + except EOFError: + break + if cobchunk.chunkname == "PolH": + verts, faces, objname, facesuv, uvcoords = read_polh(cobchunk) + mod_meshtools.create_mesh(verts, faces, objname, facesuv, uvcoords) + + ''' + object = Blender.Object.GetSelected() + obj = Blender.Object.Get(objname) + obj.loc = location + obj.rot = mod_meshtools.mat2euler(rotation_matrix) + obj.size = (transformation_matrix[0][0]/rotation_matrix[0][0], + transformation_matrix[1][1]/rotation_matrix[1][1], + transformation_matrix[2][2]/rotation_matrix[2][2]) + + ''' + else: + cobchunk.skip() + + Blender.Window.DrawProgressBar(1.0, '') # clear progressbar + file.close() + end = time.clock() + seconds = " in %.2f %s" % (end-start, "seconds") + message = "Successfully imported " + os.path.basename(filename) + seconds + mod_meshtools.print_boxed(message) + #print "objname :", objname + #print "numverts:", len(verts) + #print "numfaces:", len(faces) + +def fs_callback(filename): + read(filename) + +Blender.Window.FileSelector(fs_callback, "COB Import") + +# === Matrix Differences between Blender & trueSpace === +# +# For the 'Local Axes' values: +# The x, y, and z-axis represent a simple rotation matrix. +# This is equivalent to Blender's object matrix before it was +# combined with the object's scaling matrix. Dividing each value +# by the appropriate scaling factor (and transposing at the same +# time) produces the original rotation matrix. +# +# For the 'Current Position' values: +# This is equivalent to Blender's object matrix except that the +# last row is omitted and the xyz location is used in the last +# column. Binary format uses a 4x3 matrix, ascii format uses a 4x4 +# matrix. +# +# For Cameras: The matrix is a little confusing. diff --git a/release/scripts/unweld044.py b/release/scripts/unweld044.py new file mode 100644 index 00000000000..481aeab8aa2 --- /dev/null +++ b/release/scripts/unweld044.py @@ -0,0 +1,366 @@ +#!BPY +""" Registration info for Blender menus: <- these words are ignored +Name: 'UnWeld' +Blender: 232 +Group: 'Modifiers' +Tip: 'unweld all faces from one selected and commun vertex. Made vertex bevelling' +""" + +# ------------------------------------------ +# Un-Weld script 0.4.4 beta +# +# split all faces from one selected vertex +# (c) 2004 J-M Soler released under Blender Artistic License +#---------------------------------------------- +# Official Page : +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_faces2vertex.htm#exemple +# Communicate problems and errors on: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +#---------------------------------------------- +# Blender Artistic License +# http://download.blender.org/documentation/html/x21254.html +#--------------------------------------------- +# Changelog +#---------------------------------------------- +# 25/05 : +# -- separate choise, normal (same place) or spread at random, middle of the face +# -- works on several vertices too +# -- Quite vertex bevelling on <<lone>> vertex : create hole in faces around this +# vertex +# 03/06 : +# -- a sort of "bevelled vertex" extrusion controled by horizontal mouse +# displacement. just a beta test to the mouse control. +#---------------------------------------------- +# Page officielle : +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_faces2vertex.htm#exemple +# Communiquer les problemes et erreurs sur: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +# Blender Artistic License +# http://download.blender.org/documentation/html/x21254.html +#--------------------------------------------- +# Changelog +#---------------------------------------------- +# 25/05 : +# -- separation du choix, normal ou dispersion hasardeuse, milieu de face +# -- sommets multiples / +# -- Quite vertex bevelling on lone vertex : create hole in faces around the +# vertex +# 03/06 : +# -- a sort of "bevelled vertex" extrusion controled by horizontal mouse +# displacement +#---------------------------------------------- + +import Blender +from Blender import Noise +from Blender.Draw import * +from Blender.BGL import * + +Nr=Noise.random +decal=0.03 +t=[0.0,0.0,0.0] +pl=[] +orig=[] + +DEBUG = 0 +SUBSURF=0 +DIM=Create(1.0) + +def Tampon(v,t): + for n in range(len(v)): t[n]=t[n]+v[n] + return t + +def freeTampon(t): + for n in range(3): t[n]=0.0 + return t + +def TamponMoyen(t,f): + for n in range(3): t[n]/=len(f) + return t + +def appliqueMoyenne(v,t): + for n in range(len(v)): v[n]=t[n] + return v + +def docF(f0,f): + try: + f0.mat=f.mat + f0.uv=f.uv + f0.col=f.col + f0.image=f.image + return f0 + except: + pass + +def listConnecterFace(me,lebon): + listf2v={} + #tri des faces connectees aux sommets selectionnes + for f in me.faces: + for v in f.v: + if v==lebon: + if v.index not in listf2v.keys(): + listf2v[me.verts.index(v)]=[f] + elif f not in listf2v[me.verts.index(v)]: + listf2v[me.verts.index(v)].append(f) + return listf2v + +def creerFaceSupplementaire(me,lebon,listf2v): + global t + for f in listf2v[lebon.index]: + f0=Blender.NMesh.Face() + if result==3: t=freeTampon(t) + for v in f.v: + if result==3: t=Tampon(v,t) + if v!=lebon: + f0.append(v) + else: + if result==2: + nv=Blender.NMesh.Vert(lebon.co[0]+Nr()*decal,lebon.co[1]+Nr()*decal,lebon.co[2]+Nr()*decal) + else: + nv=Blender.NMesh.Vert(lebon.co[0],lebon.co[1],lebon.co[2]) + me.verts.append(nv) + f0.append(me.verts[me.verts.index(nv)]) + localise=me.verts.index(nv) + docF(f0,f) + + if result==3: + t=TamponMoyen(t,f0.v) + me.verts[localise]=appliqueMoyenne(me.verts[localise],t) + me.faces.append(f0) + del me.verts[me.verts.index(lebon)] + for f in listf2v[lebon.index]: + del me.faces[me.faces.index(f)] + return me + +def collecte_edge(listf2v,me,lebon): + back=0 + edgelist = [] + vertlist = [] + if DEBUG : print listf2v + for face in listf2v[lebon.index]: + if len(face.v) == 4: + vlist = [0,1,2,3,0] + elif len(face.v) == 3: + vlist = [0,1,2,0] + else: + vlist = [0,1] + for i in range(len(vlist)-1): + vert0 = min(face.v[vlist[i]].index,face.v[vlist[i+1]].index) + vert1 = max(face.v[vlist[i]].index,face.v[vlist[i+1]].index) + edgeinlist = 0 + if vert0==lebon.index or vert1==lebon.index: + for edge in edgelist: + if ((edge[0]==vert0) and (edge[1]==vert1)): + edgeinlist = 1 + edge[2] = edge[2]+1 + edge.append(me.faces.index(face)) + break + if edgeinlist==0: + edge = [vert0,vert1,1,me.faces.index(face)] + edgelist.append(edge) + + for edge in edgelist: + #print edge + if len(edge)==4: + del edgelist[edgelist.index(edge)] + + edges=len(edgelist) + if DEBUG : print 'number of edges : ',edges," Edge list : " ,edgelist + return edges, edgelist + +MouseClickG= Blender.Draw.LEFTMOUSE +MouseClickD= Blender.Draw.RIGHTMOUSE +MouseClickM= Blender.Draw.MIDDLEMOUSE + +mouse_x=1 +mouse_y=1 + +x=1 +y=1 + +debut=0 + +def D(): + size=Buffer(GL_FLOAT, 4) + glGetFloatv(GL_SCISSOR_BOX, size) + size= size.list + glColor3f(0.1, 0.1, 0.15) + glRasterPos2f(10, size[3]-16) + Text("Quit = Qkey") + glRasterPos2f(10, size[3]-36) + Text("Mouse to the Rigth = Increase") + glRasterPos2f(10, size[3]-56) + Text("Mouse to the Left = Decrease") + +def E(evt,val): + global mouse_x,x,pl,orig,me,debut + global mouse_y,y, MouseClickG,MouseClickD,MouseClickM + if (evt== QKEY): Exit() + + if (evt == MOUSEX): + mouse_x = val + pos=x-mouse_x + x=mouse_x + if pos==0: + pos=1 + deplace(pl,orig,abs(pos)/pos) + + if (evt == MOUSEY): mouse_y = val + +def BE(evt): + pass + + +def deplace(pl,orig,n): + global me, OBJECT + for p in pl: + #print p, orig,len(me.verts) + me.verts[p].co[0]+=n*orig[0] + me.verts[p].co[1]+=n*orig[1] + me.verts[p].co[2]+=n*orig[2] + me.update() + Blender.Redraw() + + +def VertexBevel(result): + global t,pl, orig,me, SUBSURF + unique=0 + for v in me.verts: + if v.sel==1: + lebon=v + unique+=1 + + if unique==1: + edges=0 + edgelist=[] + vertlist=[] + orig=lebon.no[:] + listf2v=listConnecterFace(me,lebon) + edges, edgelist = collecte_edge(listf2v,me,lebon) + for f in listf2v[lebon.index]: + f0=Blender.NMesh.Face() + for v in f.v: + if v!=lebon: + f0.append(v) + else: + nv=Blender.NMesh.Vert(lebon.co[0],lebon.co[1],lebon.co[2]) + nv.sel=1 + me.verts.append(nv) + f0.append(me.verts[me.verts.index(nv)]) + for e in edgelist: + if e[-1]==me.faces.index(f) or e[-2]==me.faces.index(f): + if me.verts.index(nv) not in e: + e.insert(0,me.verts.index(nv)) + docF(f0,f) + me.faces.append(f0) + vertlist.append([me.verts.index(nv),me.faces.index(f)]) + for e in edgelist : + del e[e.index(lebon.index)] + f0=Blender.NMesh.Face() + for n in range(3): + f0.v.append(me.verts[e[n]]) + me.faces.append(f0); + + for ve in vertlist: + t=freeTampon(t) + for v in me.faces[ve[1]].v: + t=Tampon(v,t) + t=TamponMoyen(t,me.faces[ve[1]].v) + ve.append(t[:]) + me.verts[ve[0]]=appliqueMoyenne(me.verts[ve[0]],t) + + def swap(x,y): + return y,x + + p=[[edgelist[0][0],edgelist[0][1]]] + while len(p)!=len(edgelist): + for n in range(1,len(edgelist)) : + if p[-1][1]== edgelist[n][0]: + p.append([edgelist[n][0],edgelist[n][1]]) + n+=1 + elif p[-1][1]== edgelist[n][1]: + edgelist[n][0],edgelist[n][1]=swap(edgelist[n][0],edgelist[n][1]) + p.append([edgelist[n][0],edgelist[n][1]]) + n+=1 + if len(p)%2==0: + P0=p[:(len(p))/2] ; P1=p[len(p)/2:]; P1.reverse() + for s in range(len(P0)-1): + f0=Blender.NMesh.Face() + table=[P0[s][0],P0[s][1],P1[s+1][0],P1[s+1][1]] + for t in table:f0.v.append(me.verts[t]) + me.faces.append(f0) + elif len(p) >3 : + P0=p[:(len(p)-1)/2];P1=p[(len(p)-1)/2:-1]; P1.reverse() + for s in range(len(P0)-1): + f0=Blender.NMesh.Face() + table=[P0[s][0],P0[s][1],P1[s+1][0],P1[s+1][1]] + for t in table:f0.v.append(me.verts[t]) + me.faces.append(f0) + f0=Blender.NMesh.Face() + table=[p[-1][0],P0[0][0],P1[-1][1]] + for t in table:f0.v.append(me.verts[t]) + me.faces.append(f0) + + elif len(p) ==3 : + if DEBUG :print P0,P1 + f0=Blender.NMesh.Face() + table=[p[0][0],p[0][1],p[1][1]] + for t in table:f0.v.append(me.verts[t]) + me.faces.append(f0) + + for f in listf2v[lebon.index]: + del me.faces[me.faces.index(f)] + del me.verts[me.verts.index(lebon)] + me.update() + + if me.mode&Blender.NMesh.Modes['SUBSURF']: + me.mode-=Blender.NMesh.Modes['SUBSURF'] + SUBSURF=1 + me.update() + OBJECT[0].makeDisplayList() + + if result==5: + pl=[] + for s in me.verts: + if s.sel==1: + pl.append(s.index) + Blender.Draw.Register(D,E,BE) + + """ + if SUBSURF==1 : + me.mode+=Blender.NMesh.Modes['SUBSURF'] + me.update() + OBJECT[0].makeDisplayList() + """ + else: + name = " It could leave only one selected vertex %t | ok %x1 ?" + result = Blender.Draw.PupMenu(name) + +OBJECT=Blender.Object.GetSelected() + +if len(OBJECT)!=0: + if OBJECT[0].getType()=='Mesh': + name = "Un-Weld, OK ? %t| unbind points %x1| with noise ? %x2| middle face ? %x3| static bevel vertex ? %x4| moving bevel vertex ? %x5|" + result = Blender.Draw.PupMenu(name) + if result: + me=OBJECT[0].getData() + unique=0 + if result<4: + #tri des sommets selectionnes + for v in me.verts: + if v.sel==1: + lebon=v + if DEBUG : print lebon + #dictionnaires des faces connectees aux sommets selectionnes + listf2v=listConnecterFace(me,lebon) + me=creerFaceSupplementaire(me,lebon,listf2v) + OBJECT[0].link(me) + OBJECT[0].makeDisplayList() + else: + VertexBevel(result) + OBJECT[0].makeDisplayList() + + else: + name = "Nothing to do! Are you sure ?" + result = Blender.Draw.PupMenu(name) + + diff --git a/release/scripts/uv_export.py b/release/scripts/uv_export.py index ef224b6eba8..5a494952487 100644 --- a/release/scripts/uv_export.py +++ b/release/scripts/uv_export.py @@ -28,7 +28,13 @@ Tooltip: 'Export the UV face layout of the selected object to a .TGA file' # # ***** END GPL LICENCE BLOCK ***** # -------------------------------------------------------------------------- -# thanks to jms for the tga functions +# thanks to jms for the tga functions: +# Writetga and buffer functions +# (c) 2002-2004 J-M Soler released under GPL licence +# Official Page : +# http://jmsoler.free.fr/didacticiel/blender/tutor/write_tga_pic.htm +# Communicate problems and errors on: +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender # -------------------------- # Version 1.1 # Clear a bug that crashed the script when UV coords overlapped in the same faces diff --git a/release/scripts/videoscape_export.py b/release/scripts/videoscape_export.py index 6f7b0849dfd..6cfbd3e9e1e 100644 --- a/release/scripts/videoscape_export.py +++ b/release/scripts/videoscape_export.py @@ -9,8 +9,8 @@ Tooltip: 'Export selected mesh to VideoScape File Format (*.obj)' # +---------------------------------------------------------+ # | Copyright (c) 2001 Anthony D'Agostino | -# | http://ourworld.compuserve.com/homepages/scorpius | -# | scorpius@compuserve.com | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | # | June 5, 2001 | # | Released under the Blender Artistic Licence (BAL) | # | Import Export Suite v0.5 | @@ -22,7 +22,6 @@ Tooltip: 'Export selected mesh to VideoScape File Format (*.obj)' import Blender, mod_meshtools #import time -import mod_flags # ===================================== # ====== Write VideoScape Format ====== @@ -37,7 +36,7 @@ def write(filename): mesh = Blender.NMesh.GetRaw(meshname) obj = Blender.Object.Get(objname) - if not mesh.hasVertexColours(): + if not mod_meshtools.has_vertex_colors(mesh): message = "Please assign vertex colors before exporting.\n" message += objname + " object was not saved." mod_meshtools.print_boxed(message) @@ -51,7 +50,7 @@ def write(filename): # === Write Vertex List & Vertex Colors === for i in range(len(mesh.verts)): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts") file.write("% f % f % f 0x" % tuple(mesh.verts[i].co)) for j in range(len(vcols[i])): @@ -60,7 +59,7 @@ def write(filename): # === Write Face List === for i in range(len(mesh.faces)): - if not i%100 and mod_flags.show_progress: + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces") file.write("%d " % len(mesh.faces[i].v)) # numfaceverts for j in range(len(mesh.faces[i].v)): @@ -86,7 +85,7 @@ vcolor_div = lambda u, s: [u[0]/s, u[1]/s, u[2]/s, u[3]/s] def average_vertexcolors(mesh, debug=0): vertexcolors = {} for i in range(len(mesh.faces)): # get all vcolors that share this vertex - if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Finding Shared VColors") + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Finding Shared VColors") for j in range(len(mesh.faces[i].v)): index = mesh.faces[i].v[j].index color = mesh.faces[i].col[j] @@ -95,7 +94,7 @@ def average_vertexcolors(mesh, debug=0): if debug: print 'before'; vcprint(vertexcolors) for i in range(len(vertexcolors)): # average them - if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") vcolor = [0,0,0,0] # rgba for j in range(len(vertexcolors[i])): vcolor = vcolor_add(vcolor, vertexcolors[i][j]) @@ -111,7 +110,7 @@ def average_vertexcolors_slow_1(mesh, debug=0): vertexcolors = [] i = 0 for vertex in mesh.verts: - if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") i += 1 vcolor = [0,0,0,0] # rgba shared = 0 @@ -133,7 +132,7 @@ def average_vertexcolors_slow_1(mesh, debug=0): def average_vertexcolors_slow_2(mesh, debug=0): vertexcolors = [] for i in range(len(mesh.verts)): - if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") vcolor = [0,0,0,0] # rgba shared = 0 for j in range(len(mesh.faces)): @@ -153,7 +152,7 @@ def average_vertexcolors_slow_2(mesh, debug=0): def average_vertexcolors_slow_3(mesh, debug=0): vertexcolors = [] for i in range(len(mesh.verts)): - if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") vcolor = [0,0,0,0] # rgba shared = 0 for j in range(len(mesh.faces)): diff --git a/release/scripts/wings_export.py b/release/scripts/wings_export.py new file mode 100644 index 00000000000..46112ac83fd --- /dev/null +++ b/release/scripts/wings_export.py @@ -0,0 +1,337 @@ +#!BPY + +""" +Name: 'Wings3D...' +Blender: 232 +Group: 'Export' +Tooltip: 'Export selected mesh to Wings3D File Format (*.wings)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2002 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | Feb 19, 2002 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write Wings3D File Format (*.wings) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, time, sys, os, zlib, cStringIO + +# =============================================== +# === Write The 'Header' Common To All Chunks === +# =============================================== +def write_chunkheader(data, version, tag, name): + data.write(struct.pack(">BB", version, tag)) + data.write(struct.pack(">BH", 0x64, len(name))) + data.write(name) + +# =================== +# === Write Faces === +# =================== +def write_faces(data, mesh): + numfaces = len(mesh.faces) + data.write(struct.pack(">BL", 0x6C, numfaces)) + #for i in range(numfaces): + # if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numfaces, "Writing Faces") + # data.write("\x6A") + data.write("\x6A" * numfaces) # same, but faster than the above loop + data.write("\x6A") + +# =================== +# === Write Verts === +# =================== +def write_verts(data, mesh): + numverts = len(mesh.verts) + data.write(struct.pack(">BL", 0x6C, numverts)) + for i in range(numverts): + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numverts, "Writing Verts") + data.write(struct.pack(">BLBL", 0x6C, 1, 0x6D, 24)) + #data.write("\x6c\x00\x00\x00\x01\x6D\x00\x00\x00\x30") + x, y, z = mesh.verts[i].co + data.write(struct.pack(">ddd", x, z, -y)) + data.write("\x6A") + data.write("\x6A") + +# =================== +# === Write Edges === +# =================== +def write_edges(data, mesh, edge_table): + numedges = len(edge_table) + data.write(struct.pack(">BL", 0x6C, numedges)) + keys = edge_table.keys() + keys.sort() + for key in keys: + i = edge_table[key][6] + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numedges, "Writing Edges") + + if mod_meshtools.has_vertex_colors(mesh): + r1, g1, b1 = edge_table[key][7] + r2, g2, b2 = edge_table[key][8] + data.write("\x6C\x00\x00\x00\x02") + data.write("\x68\x02\x64\x00\x05color") + data.write("\x6D\x00\x00\x00\x30") + data.write(struct.pack(">dddddd", r1, g1, b1, r2, g2, b2)) + #print "%f %f %f - %f %f %f" % (r1, g1, b1, r2, g2, b2) + else: + data.write("\x6C\x00\x00\x00\x01") # BL + + #$write_chunkheader(data, 0x68, 0x09, "edge") + data.write("\x68\x09\x64\x00\x04edge") # faster + + # Sv Ev (Reversed) + data.write(struct.pack(">BLBL", 0x62, key[1], 0x62, key[0])) + + # Lf Rf LP LS RP RS + for i in range(6): + if edge_table[key][i] < 256: + data.write(struct.pack(">BB", 0x61, edge_table[key][i])) + else: + data.write(struct.pack(">BL", 0x62, edge_table[key][i])) + + data.write("\x6A") + + data.write("\x6A") + +# =============================== +# === Write The Material Mode === +# =============================== +def write_mode(data, mesh): + data.write("\x6A") + data.write(struct.pack(">BL", 0x6C, 1)) + write_chunkheader(data, 0x68, 0x02, "mode") + if mod_meshtools.has_vertex_colors(mesh): + data.write(struct.pack(">BH6s", 0x64, 6, "vertex")) + else: + data.write(struct.pack(">BH8s", 0x64, 8, "material")) + data.write("\x6A") + +# ====================== +# === Write Material === +# ====================== +def write_material(data, mesh): + data.write("\x6A") + data.write(struct.pack(">BL", 0x6C, 1)) + write_chunkheader(data, 0x68, 0x02, "my default") + + data.write(struct.pack(">BL", 0x6C, 2)) + write_chunkheader(data, 0x68, 0x02, "maps") + data.write("\x6A") + write_chunkheader(data, 0x68, 0x02, "opengl") + + # === The Material Components === + data.write(struct.pack(">BL", 0x6C, 5)) + + write_chunkheader(data, 0x68, 0x02, "diffuse") + data.write("\x68\x04") + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + + write_chunkheader(data, 0x68, 0x02, "ambient") + data.write("\x68\x04") + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + + write_chunkheader(data, 0x68, 0x02, "specular") + data.write("\x68\x04") + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4) + + write_chunkheader(data, 0x68, 0x02, "emission") + data.write("\x68\x04") + data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4) + data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4) + + write_chunkheader(data, 0x68, 0x02, "shininess") + data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4) + + #write_chunkheader(data, 0x68, 0x02, "twosided") + #data.write(struct.pack(">BH4s", 0x64, 4, "true")) + + data.write("\x6A"*3) # use *4 if no ambient light + +# ===================== +# === Generate Data === +# ===================== +def generate_data(objname, edge_table, mesh): + data = cStringIO.StringIO() + + # === wings chunk === + write_chunkheader(data, 0x68, 0x03, "wings") + + numobjs = 1 # len(Blender.Object.GetSelected()) + data.write("\x61\x02\x68\x03") # misc bytes + data.write(struct.pack(">BL", 0x6C, numobjs)) + + # === object chunk === + write_chunkheader(data, 0x68, 0x04, "object") + data.write(struct.pack(">BH", 0x6B, len(objname))) + data.write(objname) + + # === winged chunk === + write_chunkheader(data, 0x68, 0x05, "winged") + write_edges(data, mesh, edge_table) + write_faces(data, mesh) + write_verts(data, mesh) + write_mode(data, mesh) + write_material(data, mesh) + write_ambient_light(data) + return data.getvalue() + +# =========================== +# === Write Ambient Light === +# =========================== +def write_ambient_light(data): + light = [ # A quick cheat ;) + 0x6C, 0x00, 0x00, 0x00, 0x01, 0x68, 0x02, 0x64, 0x00, 0x06, 0x6C, 0x69, + 0x67, 0x68, 0x74, 0x73, 0x6C, 0x00, 0x00, 0x00, 0x01, 0x68, 0x02, 0x6B, + 0x00, 0x07, 0x41, 0x6D, 0x62, 0x69, 0x65, 0x6E, 0x74, 0x6C, 0x00, 0x00, + 0x00, 0x08, 0x68, 0x02, 0x64, 0x00, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, + 0x6C, 0x65, 0x64, 0x00, 0x04, 0x74, 0x72, 0x75, 0x65, 0x68, 0x02, 0x64, + 0x00, 0x06, 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x64, 0x00, 0x05, 0x66, + 0x61, 0x6C, 0x73, 0x65, 0x68, 0x02, 0x64, 0x00, 0x06, 0x6F, 0x70, 0x65, + 0x6E, 0x67, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x03, 0x68, 0x02, 0x64, 0x00, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x64, 0x00, 0x07, 0x61, 0x6D, 0x62, 0x69, + 0x65, 0x6E, 0x74, 0x68, 0x02, 0x64, 0x00, 0x07, 0x61, 0x6D, 0x62, 0x69, + 0x65, 0x6E, 0x74, 0x68, 0x04, 0x63, 0x31, 0x2E, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x63, 0x31, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x63, 0x31, 0x2E, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x63, 0x31, 0x2E, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x68, 0x02, 0x64, 0x00, 0x08, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, + 0x6F, 0x6E, 0x68, 0x03, 0x63, 0x30, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x63, 0x33, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x65, + 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x63, 0x30, 0x2E, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x6A, 0x68, 0x02, 0x64, 0x00, 0x07, 0x76, 0x69, + 0x73, 0x69, 0x62, 0x6C, 0x65, 0x64, 0x00, 0x04, 0x74, 0x72, 0x75, 0x65, + 0x68, 0x02, 0x64, 0x00, 0x06, 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x64, + 0x00, 0x05, 0x66, 0x61, 0x6C, 0x73, 0x65, 0x68, 0x02, 0x64, 0x00, 0x06, + 0x79, 0x61, 0x66, 0x72, 0x61, 0x79, 0x6C, 0x00, 0x00, 0x00, 0x0B, 0x68, + 0x02, 0x64, 0x00, 0x09, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x69, 0x7A, 0x65, + 0x64, 0x64, 0x00, 0x04, 0x74, 0x72, 0x75, 0x65, 0x68, 0x02, 0x64, 0x00, + 0x05, 0x70, 0x6F, 0x77, 0x65, 0x72, 0x63, 0x31, 0x2E, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x68, 0x02, 0x64, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x64, + 0x00, 0x09, 0x68, 0x65, 0x6D, 0x69, 0x6C, 0x69, 0x67, 0x68, 0x74, 0x68, + 0x02, 0x64, 0x00, 0x07, 0x73, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x73, 0x62, + 0x00, 0x00, 0x01, 0x00, 0x68, 0x02, 0x64, 0x00, 0x05, 0x64, 0x65, 0x70, + 0x74, 0x68, 0x61, 0x03, 0x68, 0x02, 0x64, 0x00, 0x0A, 0x62, 0x61, 0x63, + 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x64, 0x00, 0x09, 0x75, 0x6E, + 0x64, 0x65, 0x66, 0x69, 0x6E, 0x65, 0x64, 0x68, 0x02, 0x64, 0x00, 0x18, + 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x5F, 0x66, + 0x69, 0x6C, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x5F, 0x48, 0x44, 0x52, 0x49, + 0x6A, 0x68, 0x02, 0x64, 0x00, 0x19, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, + 0x6F, 0x75, 0x6E, 0x64, 0x5F, 0x66, 0x69, 0x6C, 0x65, 0x6E, 0x61, 0x6D, + 0x65, 0x5F, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x6A, 0x68, 0x02, 0x64, 0x00, + 0x1A, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x5F, + 0x65, 0x78, 0x70, 0x6F, 0x73, 0x75, 0x72, 0x65, 0x5F, 0x61, 0x64, 0x6A, + 0x75, 0x73, 0x74, 0x61, 0x00, 0x68, 0x02, 0x64, 0x00, 0x12, 0x62, 0x61, + 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x5F, 0x6D, 0x61, 0x70, + 0x70, 0x69, 0x6E, 0x67, 0x64, 0x00, 0x05, 0x70, 0x72, 0x6F, 0x62, 0x65, + 0x68, 0x02, 0x64, 0x00, 0x10, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, + 0x75, 0x6E, 0x64, 0x5F, 0x70, 0x6F, 0x77, 0x65, 0x72, 0x63, 0x31, 0x2E, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x6A, 0x68, 0x02, 0x64, 0x00, 0x07, 0x76, + 0x69, 0x73, 0x69, 0x62, 0x6C, 0x65, 0x64, 0x00, 0x04, 0x74, 0x72, 0x75, + 0x65, 0x68, 0x02, 0x64, 0x00, 0x06, 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, + 0x64, 0x00, 0x05, 0x66, 0x61, 0x6C, 0x73, 0x65, 0x6A, 0x6A, 0x6A] + data.write("".join(map(chr, light))) + +# ========================== +# === Write Wings Format === +# ========================== +def write(filename): + start = time.clock() + + objects = Blender.Object.GetSelected() + objname = objects[0].name + meshname = objects[0].data.name + mesh = Blender.NMesh.GetRaw(meshname) + obj = Blender.Object.Get(objname) + + try: + edge_table = mod_meshtools.generate_edgetable(mesh) + except: + edge_table = {} + message = "Unable to generate\nEdge Table for mesh.\n" + message += "Object name is: " + meshname + mod_meshtools.print_boxed(message) + #return + + if 0: + import Tkinter, tkMessageBox + sys.argv=['wings.pyo','wings.pyc'] # ? + + #Tkinter.NoDefaultRoot() + win1 = Tkinter.Tk() + ans = tkMessageBox.showerror("Error", message) + win1.pack() + print ans + if ans: + win1.quit() + win1.mainloop() + + else: + from Tkinter import Label + sys.argv = 'wings.py' + widget = Label(None, text=message) + #widget.title("Error") + widget.pack() + widget.mainloop() + + data = generate_data(objname, edge_table, mesh) + dsize = len(data) + Blender.Window.DrawProgressBar(0.98, "Compressing Data") + data = zlib.compress(data, 6) + fsize = len(data)+6 + header = "#!WINGS-1.0\r\n\032\04" + misc = 0x8350 + + file = open(filename, "wb") + file.write(header) + file.write(struct.pack(">L", fsize)) + file.write(struct.pack(">H", misc)) + file.write(struct.pack(">L", dsize)) + file.write(data) + + # Blender.Window.RedrawAll() + Blender.Window.DrawProgressBar(1.0, '') # clear progressbar + file.close() + end = time.clock() + seconds = " in %.2f %s" % (end-start, "seconds") + message = "Successfully exported " + os.path.basename(filename) + seconds + '\n\n' + message += "objname : " + objname + '\n' + message += "faces : " + `len(mesh.faces)` + '\n' + message += "edges : " + `len(edge_table)` + '\n' + message += "verts : " + `len(mesh.verts)` + '\n' + mod_meshtools.print_boxed(message) + +def fs_callback(filename): + if filename.find('.wings', -6) <= 0: filename += '.wings' + write(filename) + +Blender.Window.FileSelector(fs_callback, "Wings3D Export") diff --git a/release/scripts/wings_import.py b/release/scripts/wings_import.py new file mode 100644 index 00000000000..85d5fa377ad --- /dev/null +++ b/release/scripts/wings_import.py @@ -0,0 +1,288 @@ +#!BPY + +""" +Name: 'Wings3D...' +Blender: 232 +Group: 'Import' +Tooltip: 'Import Wings3D File Format (*.wings)' +""" + +# +---------------------------------------------------------+ +# | Copyright (c) 2002 Anthony D'Agostino | +# | http://www.redrival.com/scorpius | +# | scorpius@netzero.com | +# | Feb 19, 2002 | +# | Released under the Blender Artistic Licence (BAL) | +# | Import Export Suite v0.5 | +# +---------------------------------------------------------+ +# | Read and write Wings3D File Format (*.wings) | +# +---------------------------------------------------------+ + +import Blender, mod_meshtools +import struct, time, sys, os, zlib, cStringIO + +# ============================================== +# === Read The 'Header' Common To All Chunks === +# ============================================== +def read_chunkheader(data): + data.read(2) #version, tag = struct.unpack(">BB", data.read(2)) + misc, namelen = struct.unpack(">BH", data.read(3)) + name = data.read(namelen) + return name + +# ============================== +# === Read The Material Mode === +# ============================== +def read_mode(data): + data.read(5) # BL + read_chunkheader(data) # "mode" + misc, namelen = struct.unpack(">BH", data.read(3)) + data.read(namelen) + data.read(1) # 6A + +# ======================= +# === Read Hard Edges === +# ======================= +def read_hardedges(data): + tag = data.read(1) + if tag == '\x6A': + return # There are no hard edges + elif tag == '\x6B': + numhardedges, = struct.unpack(">H", data.read(2)) + print "numhardedges:", numhardedges + for i in range(numhardedges): + data.read(1) + elif tag == '\x6C': + numhardedges, = struct.unpack(">L", data.read(4)) + print "numhardedges:", numhardedges + for i in range(numhardedges): + misc = data.read(1) + if misc == '\x61': # next value is stored as a byte + data.read(1) + elif misc == '\x62': # next value is stored as a long + data.read(4) + data.read(1) # 6A + else: + print tag + +# ================== +# === Read Edges === +# ================== +def read_edges(data): + misc, numedges = struct.unpack(">BL", data.read(5)) + edge_table = {} # the winged-edge table + for i in range(numedges): + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numedges, "Reading Edges") + misc, etype = struct.unpack(">BL", data.read(5)) + if etype == 2: # Vertex Colors + data.read(10) # or read_chunkheader(data) # "color" + data.read(5) # BL + r1,g1,b1,r2,g2,b2 = struct.unpack(">dddddd", data.read(48)) + #print "%3d %3d %3d | %3d %3d %3d" % (r1*255,g1*255,b1*255,r2*255,g2*255,b2*255), + #print "%f %f %f | %f %f %f" % (r1, g1, b1, r2, g2, b2) + data.read(9) # or read_chunkheader(data) # "edge" + edge = [] # the eight entries for this edge + for e in range(8): # Sv Ev | Lf Rf | Lp Ls | Rp Rs + misc = data.read(1) + if misc == '\x61': # next value is stored as a byte + entry, = struct.unpack(">B", data.read(1)) + edge.append(entry) + elif misc == '\x62': # next value is stored as a long + entry, = struct.unpack(">L", data.read(4)) + edge.append(entry) + edge_table[i] = edge + data.read(1) # 6A + data.read(1) # 6A + return edge_table + +# ================== +# === Read Faces === +# ================== +def read_faces(data): + misc, numfaces = struct.unpack(">BL", data.read(5)) + for i in range(numfaces): + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces") + if data.read(1) == '\x6C': # a material follows + data.read(4) + read_chunkheader(data) + misc, namelen = struct.unpack(">BH", data.read(3)) + materialname = data.read(namelen) + data.read(1) + data.read(1) # 6A + return numfaces + +# ================== +# === Read Verts === +# ================== +def read_verts(data): + misc, numverts = struct.unpack(">BL", data.read(5)) + verts = [] # a list of verts + for i in range(numverts): + if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts") + data.read(10) + x, y, z = struct.unpack(">ddd", data.read(24)) # double precision + verts.append((x, -z, y)) + data.read(1) # 6A + data.read(1) # 6A + return verts + +# ======================= +# === Make Face Table === +# ======================= +def make_face_table(edge_table): # For Wings + face_table = {} + for i in range(len(edge_table)): + Lf = edge_table[i][2] + Rf = edge_table[i][3] + face_table[Lf] = i + face_table[Rf] = i + return face_table + +# ======================= +# === Make Vert Table === +# ======================= +def make_vert_table(edge_table): # For Wings + vert_table = {} + for i in range(len(edge_table)): + Sv = edge_table[i][0] + Ev = edge_table[i][1] + vert_table[Sv] = i + vert_table[Ev] = i + return vert_table + +# ================== +# === Make Faces === +# ================== +def make_faces(edge_table): # For Wings + face_table = make_face_table(edge_table) + faces=[] + for i in range(len(face_table)): + face_verts = [] + current_edge = face_table[i] + while(1): + if i == edge_table[current_edge][3]: + next_edge = edge_table[current_edge][7] # Right successor edge + next_vert = edge_table[current_edge][0] + else: + next_edge = edge_table[current_edge][5] # Left successor edge + next_vert = edge_table[current_edge][1] + face_verts.append(next_vert) + current_edge = next_edge + if current_edge == face_table[i]: break + face_verts.reverse() + faces.append(face_verts) + return faces + +# ======================= +# === Dump Wings File === +# ======================= +def dump_wings(filename): + import pprint + start = time.clock() + file = open(filename, "rb") + header = file.read(15) + fsize, = struct.unpack(">L", file.read(4)) # file_size - 19 + misc, = struct.unpack(">H", file.read(2)) + dsize, = struct.unpack(">L", file.read(4)) # uncompressed data size + data = file.read(fsize-6) + file.close() + data = zlib.decompress(data) + if dsize != len(data): print "ERROR: uncompressed size does not match." + data = cStringIO.StringIO(data) + print "header:", header + print read_chunkheader(data) # === wings chunk === + data.read(4) # misc bytes + misc, numobjs, = struct.unpack(">BL", data.read(5)) + print "filename:", filename + print "numobjs :", numobjs + for obj in range(numobjs): + print read_chunkheader(data) # === object chunk === + misc, namelen = struct.unpack(">BH", data.read(3)) + objname = data.read(namelen) + print read_chunkheader(data) # === winged chunk === + edge_table = read_edges(data) + numfaces = read_faces(data) + verts = read_verts(data) + read_hardedges(data) + + face_table = {} # contains an incident edge + vert_table = {} # contains an incident edge + for i in range(len(edge_table)): + face_table[edge_table[i][2]] = i # generate face_table + face_table[edge_table[i][3]] = i + vert_table[edge_table[i][0]] = i # generate vert_table + vert_table[edge_table[i][1]] = i + + print "objname :", objname + print "numedges:", len(edge_table) + print "numfaces:", numfaces + print "numverts:", len(verts) + print + print "Ä"*79 + print "edge_table:" + pprint.pprint(edge_table) + #for i in range(len(edge_table)): print "%2d" % (i), edge_table[i] + print + print "face_table:" + pprint.pprint(face_table) + #for i in range(len(face_table)): print "%2d %2d" % (i, face_table[i]) + print + print "vert_table:" + pprint.pprint(vert_table) + #for i in range(len(vert_table)): print "%2d %2d" % (i, vert_table[i]) + file.close() + end = time.clock() + print '\a\r', + sys.stderr.write("\nDone in %.2f %s" % (end-start, "seconds")) + +# ========================= +# === Read Wings Format === +# ========================= +def read(filename): + start = time.clock() + file = open(filename, "rb") + header = file.read(15) + fsize, = struct.unpack(">L", file.read(4)) # file_size - 19 + misc, = struct.unpack(">H", file.read(2)) + dsize, = struct.unpack(">L", file.read(4)) # uncompressed data size + data = file.read(fsize-6) + #print file.tell(), "bytes" + file.close() + Blender.Window.DrawProgressBar(1.0, "Decompressing Data") + data = zlib.decompress(data) + data = cStringIO.StringIO(data) + read_chunkheader(data) # wings chunk + data.read(4) # misc bytes + misc, numobjs = struct.unpack(">BL", data.read(5)) + message = "Successfully imported " + os.path.basename(filename) + '\n\n' + message += "%s %8s %8s %8s\n" % ("Object".ljust(15), "faces", "edges", "verts") + message += "%s %8s %8s %8s\n" % ("ÄÄÄÄÄÄ".ljust(15), "ÄÄÄÄÄ", "ÄÄÄÄÄ", "ÄÄÄÄÄ") + + for obj in range(numobjs): + read_chunkheader(data) # object chunk + misc, namelen = struct.unpack(">BH", data.read(3)) + objname = data.read(namelen) + read_chunkheader(data) # winged chunk + edge_table = read_edges(data) + numfaces = read_faces(data) + verts = read_verts(data) + read_hardedges(data) + read_mode(data) + faces = make_faces(edge_table) + message += "%s %8s %8s %8s\n" % (objname.ljust(15), len(faces), len(edge_table), len(verts)) + mod_meshtools.create_mesh(verts, faces, objname) + + material = data.read() + #for i in material[0:6]: print "%02X" % ord(i), + #print + Blender.Window.DrawProgressBar(1.0, "Done") # clear progressbar + data.close() + end = time.clock() + seconds = "\nDone in %.2f %s" % (end-start, "seconds") + message += seconds + mod_meshtools.print_boxed(message) + +def fs_callback(filename): + read(filename) + +Blender.Window.FileSelector(fs_callback, "Wings3D Import") |