######################
# wire and tesselate project
# jean-michel soler january/october
#                  2000
######################
import Blender
from Blender import Object
from Blender.Object import *
from Blender import NMesh 
from Blender.NMesh import *
from Blender.Draw import *
from Blender.BGL import *

fr=    { 'Lang':'Eng',
         'EpXY':"Epaisseur XY : ",
         'EpXY_doc':"Etablit l'epaisseur a partir du bord de la face",
         'EpZ':"Epaisseur Z",
         'EpZ_doc':"indique s'il faut calculer lepaisseur a partir de la face" ,
         'NgZ':"Active -Z",
         'NgZ_doc':"inverse la direction de la normale",
         'FintTG':"FaceinterneTG",
         'FintTG_doc':"Ajoute une face interne",
         'EpQZ':"Epaisseur Z : ",
         'EpQZ_doc':"Etablit l'epaisseur a partir de la surface de la face dans le sens de la normale",
         'FrgT':"Fragmentation totale, face pour face  ",
         'FrgT_doc':"Effectue l'equivalent de split sur tout le mesh",
         'T1':"Fragmention : explose l'objet courant",
         'T2':"sans effectuer les autres operations.",
         'Act':"Action"}
 
ang={   'Lang':'Fra',
         'EpXY':"XY Thickness : ",
         'EpXY_doc':"Set thickness from the Face border.",
         'EpZ':"Set Z Thickness",
         'EpZ_doc':"Set if script use or not the Z thickness.",
         'NgZ':"Neg Z",
         'NgZ_doc':"reverse normal direction",
         'FintTG':"Unset Intern Face",
         'FintTG_doc':"Add (or not) an internal face.",
         'EpQZ':"Z Thickness : ",
         'EpQZ_doc':"Set thickness from the the face in the normal direction.",
         'FrgT':"Set Total Fragmentation by Face",
         'FrgT_doc':"Eqivalent to split on all the mesh",
         'T1':"Split All Mesh",
         'T2':"without doing the others actions",
         'Act':"Make it",
         'iteration':"loop upon number. Reset to non at the end of "  }
 
lg=[fr,ang]
lang=Create(0)

#epaisseur/largeur de la bande
#laissee en bordure de la facette
epaisseur=Create(0.95)

#distance au plan de la face originale
#modifie les coordonees des sommets qui
#limitent la bande
distance=Create(0.95)

#bouton toggle/booleen pour l'option 
#"distance"
DistanceTG=Create(0)

#bouton toggle/booleen pour l'option 
#d'inversion de la distance, en standard
#orientee vers l'exterieur de la facette
DistNegTG=Create(0)

#bouton toggle/booleen pour l'option 
#de conservation de la face interne
FaceinterneTG=Create(0)

#bouton toggle/booleen pour l'option 
#d'eclatement du reseau de facette
#en facette separee
SplitTotalTG=Create(0)

#bouton pour le niveau d'iteration
Iteration=Create(1)

#accumulateur pour calculer le centre
#du reseau de facette
accu1=[0.0,0.0,0.0]

#accumulateur pour calculer le centre
#la facette
accu2=[0.0,0.0,0.0]

#table pour la position courante de la derniere
#facette et du dernier point dans leur liste 
#respective
dern_long=[0,0]

n=[0.0,0.0,0.0]

n0=0
p0=0

a=0
b=0
c=0
d=0

locZ=[0.0,0.0,0.0]

#coefficients du plan
def  EquationPlan (v1,v2,v3):
    global a,b,c,d
    X1 =v1.co[0] 
    Y1 =v1.co[1]
    Z1 =v1.co[2]
    X2 =v2.co[0]
    Y2 =v2.co[1] 
    Z2 =v2.co[2] 
    X3 =v3.co[0] 
    Y3 =v3.co[1]
    Z3 =v3.co[2] 
    a  = Y1 * (Z2 - Z3) + Y2 * (Z3 - Z1) + Y3 * (Z1 - Z2)
    b  = -X1 * (Z2 - Z3) + X2 * (Z1 - Z3) - X3 * (Z1 - Z2)
    c  = X1 * (Y2 - Y3) - X2 * (Y1 - Y3) + X3 * (Y1 - Y2)
    #d  = -X1*(Y2*Z3-Y3*Z2)+X2*(Y1*Z3-Y3*Z1)-X3*(Y1*Z2-Y2*Z1)

    
#fonction de fractionnement de face
def tesselate(me,loc,nom,epaisseur):
    global dern_long,n0,p0,n,accu1,accu2,DistanceTG,FaceinterneTG,DistNegTG,SplitTotalTG
    me2=Blender.NMesh.GetRaw()
    if SplitTotalTG.val==0:
            for v in me.verts:
                v1= Blender.NMesh.Vert(0.0,0.0,0.0)
                v1=v
                me2.verts.append(v1)

            for f in me.faces:
                f1=Blender.NMesh.Face()
                f1=f
                me2.faces.append(f1)
            
            #reperer la fin des listes de points et de facettes
            dern_long[0]=len(me.faces)
            dern_long[1]=len(me.verts)
            
            #accumulateur pour trouver le centre geometrique du mesh
            lgf=len(me.faces)
            
            #boucler sur la liste des faces
            for n1 in range(dern_long[0]):
                face=me.faces[n1]
                accu2=[0.0,0.0,0.0]

                lgf1=len(face.v)
                #boucler sur la liste des vertices>points de chaque face
                for v in face.v:
                    #boucler sur les coordonnees de chaque point
                    for n0 in range(len(accu1)):
                        #additionner les valeurs pour trouver le centre geometrique
                        n[n0]=n[n0]+v.co[n0]
                        #meme operation sur la face actuelle
                        accu2[n0]=accu2[n0]+v.co[n0]
                    n0=0

                #centre geometrique de la facette
                for n0 in range(len(accu2)):
                    accu2[n0]=accu2[n0]/(lgf1*1.0)
                
                if DistanceTG.val:
                     dv=face.v
                     EquationPlan (dv[0],dv[1],dv[2])
                     if DistNegTG.val:
                        locZ=[-a*distance.val,-b*distance.val,-c*distance.val]
                     else:
                        locZ=[a*distance.val,b*distance.val,c*distance.val]
                else:
                     locZ=[0.0,0.0,0.0]

                #creation de nouveaux points à l'interieur de la facette    
                for v in face.v:
                    #appel de la methode d'ajout de point
                    v1= Blender.NMesh.Vert(0.0, 0.0, 0.0)
                    #calculer la position
                    for n0 in range(len(accu2)):
                        v1.co[n0]=(v.co[n0]-accu2[n0])*epaisseur.val+accu2[n0]+locZ[n0]


                    #ajouter le point à la liste
                    me.verts.append(v1)
                    me2.verts.append(v1)
                n0=0

                #ne pas depasser la fin de la liste des points de cette facette
                n2=len(face.v)

                f1= Blender.NMesh.Face()
                f1.v.append(face.v[n2-1])
                f1.v.append(face.v[0])
                f1.v.append(me.verts[dern_long[1]])
                f1.v.append(me.verts[dern_long[1]+n2-1])
                me2.faces.append(f1)
            
            #boucler sur les points de cette facette
                for n3 in range(n2-1):
                    #creation des facettes supplémentaires 
                    f1= Blender.NMesh.Face()
                    f1.v.append(face.v[n3])
                    f1.v.append(face.v[n3+1])
                    f1.v.append(me.verts[dern_long[1]+n3+1])
                    f1.v.append(me.verts[dern_long[1]+n3])
                    
                    if (n3==0): 
                        me2.faces[n1]=f1
                    else:
                        me2.faces.append(f1)

            #boucler sur les points de cette facette
                if FaceinterneTG.val:
                   f1= Blender.NMesh.Face()
                   for n3 in range(n2):
                       #creation des facettes supplémentaires 
                       f1.v.append(me.verts[dern_long[1]+n3])
                    
                   me2.faces.append(f1)

                dern_long[1]=len(me.verts)
    else:
           for f in me.faces:
                f1=Blender.NMesh.Face()
                for v in f.v:
                  v1= Blender.NMesh.Vert(v.co[0],v.co[1],v.co[2])
                  
                  me2.verts.append(v1)
                  f1.v.append(me2.verts[len(me2.verts)-1]) 
                me2.faces.append(f1)

    #me2.has_col= 0
    #me2.has_uvco= 0                
    Blender.NMesh.PutRaw(me2,nom)        
        
def testselect(test,epaisseur):
    ob= Blender.Object.GetSelected()
    if len(ob)<1:
        return
    ob=ob[0]
    me=ob.data
    nom=me.name
    if (me==None):
        return
    tesselate(me,ob.loc,nom,epaisseur)

def draw():
    global lang,epaisseur,distance,DistanceTG,FaceinterneTG,DistNegTG,SplitTotalTG,Iteration
    glColor3f(0.7, 0.7, 0.7)
    glClear(GL_COLOR_BUFFER_BIT)
    glColor3f(0.1, 0.1, 0.15)
    glRasterPos2f(20, 210)

    Text("Script Python de Tessalisation")

    glRasterPos2f(20, 190)
    Text("Jean-michel Soler, Octobre 2000")
    l=int(lang.val)
    lang = Toggle(lg[l]['Lang'], 2, 220, 200, 60, 18, lang.val )
    epaisseur=Slider(lg[l]['EpXY'], 2, 20, 160, 260, 18, epaisseur.val, 0.0, 0.99, 0,lg[l]['EpXY_doc'])
    DistanceTG = Toggle(lg[l]['EpZ'], 2, 20, 120, 180, 18, DistanceTG.val, lg[l]['EpZ_doc'])
    DistNegTG = Toggle(lg[l]['NgZ'], 2, 200, 120, 80, 18, DistNegTG.val, lg[l]['NgZ_doc'])

    FaceinterneTG = Toggle(lg[l]['FintTG'], 4, 20, 100, 260, 18, FaceinterneTG.val, lg[l]['FintTG_doc'])
    distance=Slider(lg[l]['EpQZ'], 2, 20, 140, 260, 18, distance.val, 0.001, 1.99,0,lg[l]['EpQZ_doc'])

    Iteration = Number("Iteration: ", 2, 20, 35, 260, 18, Iteration.val,0,8 )
    
    glRasterPos2f(20, 89)
    Text(lg[l]['T1'])

    glRasterPos2f(20, 77)
    Text(lg[l]['T2'])
      
    
    SplitTotalTG = Toggle(lg[l]['FrgT'], 4, 20, 55, 260, 18, SplitTotalTG.val, lg[l]['FrgT_doc'])

    #boutons de sortie
    Button("Exit", 1, 40, 10, 80, 19)
    #bouton de cration de la forme
    Button(lg[l]['Act'], 3, 140, 10, 80, 19)

def event(evt, val):    
    if (evt== QKEY and not val): Exit()

def bevent(evt):
    global epaisseur,Iteration
    if   (evt== 1):
        Exit()

    elif (evt== 3):
       while Iteration.val!=0:
            testselect(0,epaisseur)
            Iteration.val=Iteration.val-1
       Iteration.val=1
       Blender.Window.Redraw()     
       
     
    elif (evt==5) or (evt==2):
        Blender.Window.Redraw()

Register(draw, event, bevent)



