Skocz do zawartości

L-systemy dla maya


rakson23

Rekomendowane odpowiedzi

Po sesji jako ze rozpoczynam ostatni semestr napisanie skryptu do mayki jest jedna z czesci pracy magisterskiej i tak sie zastanawiam czy ma ktos jakies informacje na temat pozycji książkowych o l-systemach oprocz algorytmic beauty of plants.

 

Jeśli tak to z góry dzieki z pomoc

Odnośnik do komentarza
Udostępnij na innych stronach

  • Odpowiedzi 12
  • Created
  • Ostatniej odpowiedzi

Top Posters In This Topic

Jak już mówiłem, pracuje nad skryptem tworzącym roślinność przy pomocy l-systemów dla maya i teraz mam prośbe czy ktoś mógłby odpalić ten skrypt taki jak go wklejam i powiedziec czy sie nie wywalił?

 

import pymel.core as pm
import random
poczatek=[0,0,0]
alf=['F','[',']','+','-','V','^']
pozycjaX=0
pozycjaY=0
pozycjaZ=0
lista=[]

class ParametryLSystemu:
   def __init__(self,prze,ka,oprze,oka):
       self.przesuniecie=prze
       self.katobrotu=ka
       self.odchyleniePrzesuniecia=oprze
       self.odchylenieKata=oka

class GeneratorLSystemu:

   def __init__(self,iteracje,aksjomat,regula):
       if (iteracje>5):
           self.iter=5
       else:            
           self.iter=iteracje
       self.aks=aksjomat
       self.reg=regula              

   def GenerujLString(self):  
       lString="" 
       while (self.iter>0):
           drzewo=""
           for i in range (len(self.aks)):
               if self.aks[i]=='F':
                   drzewo=drzewo+self.reg
               else:
                   drzewo=drzewo+self.aks[i]
           self.aks=drzewo            
           self.iter=self.iter-1
       return self.aks

class InterpretatorLSystemu:

   def __init__(self,napis):
       self.ciag=napis
   def wypisz(self):
       print len(self.ciag)

   def sprawdzDlugosc(self):
       return len(self.ciag)  

   def dodajKrzywa(self,indeks,dlugosc,odchyld):
       randomizacja=float(random.randint(-odchyld,odchyld))
       dlugosc=float(dlugosc+(dlugosc*randomizacja/100))   
       #print dlugosc        
       pm.curve (d=1,p=[(0, 0, 0),(0,dlugosc,0)], n='konar'+str(indeks))

   def obroc(self,ostatni,kat,odchylk,znak):
       randomizacja=float(random.randint(-odchylk,odchylk))      
       kat=float(kat+(kat*randomizacja/100))

       if (znak=='+'):        
           pm.rotate (ostatni,[kat,0,0])
       elif (znak=='-'):
           pm.rotate (ostatni,[-kat,0,0])
       elif (znak=='^'):
           pm.rotate (ostatni,[0,0,kat])
       elif (znak=='V'):
           pm.rotate (ostatni,[0,0,-kat])

   def ustawRelacje(self,dziecko,rodzic):
       pm.parent (dziecko,rodzic, relative=True)


   def sprawdzZnak(self,indeks):      
       znak=self.ciag[indeks]
       return znak

   def sprawdzPozycje(self,nazwa):
       infoNode=pm.pointOnCurve (nazwa,ch=True,pr=1)
       pozycjaX= pm.getAttr(infoNode+".positionX")
       pozycjaY= pm.getAttr(infoNode+".positionY")
       pozycjaZ= pm.getAttr(infoNode+".positionZ")
       return pozycjaX,pozycjaY,pozycjaZ

   def odlozNaStos(self,ostat):
       lista.append(ostat)

   def pobierzZeStosu(self):
       ost=lista.pop()
       return ost
   def interpretujLString(self,przes,obr,odchp,odchk):          

       igalezi=0            
       i=0
       pozycjaX=0
       pozycjaY=0
       pozycjaZ=0

       pm.createNode('transform', n='korzen')
       ostatni='korzen'
       przedostatni=''   
       dlugoscLString=self.sprawdzDlugosc()   
       przesuniecie=przes
       katobr=obr
       odchylk=odchk
       odchylprze=odchp   

       while(i            aktualnyZnak=self.sprawdzZnak(i)                 
           print 'znak nr: ',i+1,' z: ',dlugoscLString 
           if (aktualnyZnak=='F'):
               self.dodajKrzywa(igalezi,przesuniecie,odchylprze)

               przedostatni=ostatni
               ostatni='konar'+str(igalezi)
               self.ustawRelacje(ostatni,przedostatni)
               pozycja=self.sprawdzPozycje('konar'+str(igalezi))
               pozycjaX=pozycja[0]
               pozycjaY=pozycja[1]
               pozycjaZ=pozycja[2]
               igalezi=igalezi+1
               pm.createNode('transform', n='wezel'+str(i))
               przedostatni=ostatni
               ostatni='wezel'+str(i)                
               self.ustawRelacje(ostatni,przedostatni)
               pm.move (ostatni,pozycjaX,pozycjaY,pozycjaZ)

           elif (aktualnyZnak=='+' or aktualnyZnak=='-' or aktualnyZnak=='^' or aktualnyZnak=='V'):             
               self.obroc(ostatni,katobr,odchylk,aktualnyZnak)                

           elif (aktualnyZnak=='['):
               pm.createNode ('transform', n='wezel'+str(i))
               self.odlozNaStos(ostatni)                
               przedostatni=ostatni
               ostatni='wezel'+str(i)
               self.ustawRelacje(ostatni,przedostatni)

           elif (aktualnyZnak==']'):
               print przedostatni, ostatni                
               ostatni=self.pobierzZeStosu()
           i=i+1

drzewo=GeneratorLSystemu(8,"F","F+F−F−F+F")
string=drzewo.GenerujLString()
parametry=ParametryLSystemu(10,90,0,0)
interpretacja=InterpretatorLSystemu(string)
interpretacja.interpretujLString(parametry.przesuniecie,parametry.katobrotu,parametry.odchyleniePrzesuniecia,parametry.odchylenieKata)

Odnośnik do komentarza
Udostępnij na innych stronach

Po drobnej przerwie wracam do skryptu. Właściwie to przepisałem dużą część od początku, oprócz krawędziowego przepisywania reguł dodałem węzłowe, raczej nie ma już problemu z wywalaniem się skryptu(chociaż nie próbowałem z jakimiś ogromnymi długościami L-Stringa).

 

Generator w chwili obecnej zamiast liści i kwiatów wstawia w ich miejscu plane więc spokojnie z reguł można wyrzucić litery L i K jeśli jakieś są.

Oprócz tego nie ma jeszcze GUI, ale to dlatego, że to będzie napisane jako ostatnie. W chwili obecnej zajmuje się implementacją parametrycznych L-Systemów w skrypcie i na tych chyba zakończę pracę nad tą wersją skryptu.

 

A tym czasem zapraszam do testowania.

 

 

import pymel.core as pm
import random
alf=['F','[',']','+','-','V','^','']
lista=[]
class ParametryLSystemu:
   def __init__(self,przes,kat,oprzes,okat):
       self.przesuniecie=przes
       self.katobrotu=kat
       self.odchyleniePrzesuniecia=oprzes
       self.odchylenieKata=okat


class obiektStos:
   def __init__(self,pozycjaX,pozycjaY,pozycjaZ,rotacjaX,rotacjaY,rotacjaZ):
       self.pozX=pozycjaX
       self.pozY=pozycjaY
       self.pozZ=pozycjaZ
       self.rotX=rotacjaX
       self.rotY=rotacjaY
       self.rotZ=rotacjaZ

class GeneratorLSystemuE:

   def __init__(self,iteracje,aksjomat,reguly):
       if (iteracje>7):
           self.iter=7
       else:            
           self.iter=iteracje
       self.aks=aksjomat
       self.reg=reguly             

   def GenerujLStringE(self):  
       lString="" 
       while (self.iter>0):
           drzewo=""
           aktualna=random.randint(0,len(self.reg)-1)

           for i in range (len(self.aks)):
               if self.aks[i]=='F':                   
                   drzewo=drzewo+self.reg[aktualna]
               else:
                   drzewo=drzewo+self.aks[i]
           self.aks=drzewo            
           self.iter=self.iter-1
       return self.aks

class GeneratorLSystemuN:

   def __init__(self,iteracje,aksjomat,reguly):
       if (iteracje>7):
           self.iter=7
       else:            
           self.iter=iteracje
       self.aks=aksjomat
       self.reg=reguly           

   def GenerujLStringN(self):  
       lString="" 
       while (self.iter>0):
           drzewo=""          
           for i in range (len(self.aks)):
               if self.aks[i]=='F':                   
                   drzewo=drzewo+self.reg[0]
               elif self.aks[i]=='Z':
                   drzewo=drzewo+self.reg[1]
               elif self.aks[i]=='X':
                   drzewo=drzewo+self.reg[2]
               elif self.aks[i]=='C':
                   drzewo=drzewo+self.reg[3]
               elif self.aks[i]=='V':
                   drzewo=drzewo+self.reg[4]
               elif self.aks[i]=='B':    
                   drzewo=drzewo+self.reg[5]
               elif self.aks[i]=='N':              
                   drzewo=drzewo+self.reg[6]
               elif self.aks[i]=='M':              
                   drzewo=drzewo+self.reg[7]
               else:
                   drzewo=drzewo+self.aks[i]
           self.aks=drzewo            
           self.iter=self.iter-1
       return self.aks        


class InterpretatorLSystemu:

   def __init__(self,napis):
       self.ciag=napis
   def wypisz(self):
       print len(self.ciag)

   def sprawdzDlugosc(self):
       return len(self.ciag)  

   def dodajKrzywa(self,indeks,dlugosc):
       pm.curve (d=1,p=[(0, 0, 0),(0,dlugosc,0)], n='konar'+str(indeks))

   def dodajCylinder (self,indeks,dlugosc):
       pm.polyCylinder(n='konar'+str(indeks),h=dlugosc,r=0.25)    
       pm.move('konar'+str(indeks),0,dlugosc/2.0,0) 
       pm.polyDelFacet('konar'+str(indeks)+'.f[20]','konar'+str(indeks)+'.f[21]')
       pm.makeIdentity('konar'+str(indeks),apply=True, t=1)

   def randomdlugosci(self,dlugosc,odchyld):
       randomizacja=float(random.randint(-odchyld,odchyld))
       dlugosc=float(dlugosc+(dlugosc*randomizacja/100))   
       return dlugosc

   def randomKata(self,kat,odchylk):
       randomizacja=float(random.randint(-odchylk,odchylk))
       kat=float(kat+(kat*randomizacja/100.0))
       return kat

   def dodajLisc(self,indeks):
       pm.polyPlane(n='lisc'+str(indeks),sw=1,sh=1)

   def dodajKwiat(self,indeks):
       pm.polyPlane(n='kwiat'+str(indeks),sw=1,sh=1)

   def dodajGeometrie(self,indeks,dlugosc,rodzaj):
       if (rodzaj=='krzywa'):
           self.dodajKrzywa(indeks,dlugosc)
       elif (rodzaj=='cylinder'):
           self.dodajCylinder(indeks,dlugosc)


   def obroc(self,kat,odchylk,znak):
       randomizacja=float(random.randint(-odchylk,odchylk))      
       kat=float(kat+(kat*randomizacja/100)) 
       print kat      
       if (znak=='+'):        
           pm.rotate ('pomocnik',[kat,0,0],relative=True,objectSpace=True)
       elif (znak=='-'):
           pm.rotate ('pomocnik',[-kat,0,0],relative=True,objectSpace=True)
       elif (znak=='^'):
           pm.rotate ('pomocnik',[0,0,kat],relative=True,objectSpace=True)
       elif (znak=='&'):
           pm.rotate ('pomocnik',[0,0,-kat],relative=True,objectSpace=True)
       elif (znak=='            pm.rotate ('pomocnik',[0,kat,0],relative=True,objectSpace=True)
       elif (znak=='>'):
           pm.rotate ('pomocnik',[0,-kat,0],relative=True,objectSpace=True)            

   def sprawdzZnak(self,indeks):      
       znak=self.ciag[indeks]
       return znak

   def odlozNaStos(self,ostat):
       lista.append(ostat)

   def pobierzZeStosu(self):
       ost=lista.pop()
       return ost.pozX,ost.pozY,ost.pozZ,ost.rotX,ost.rotY,ost.rotZ

   def interpretujLString(self,przes,obr,odchp,odchk):          
       igalezi=0
       iliscia=0
       ikwiata=0            
       i=0       
       dlugoscLString=self.sprawdzDlugosc()   
       przesuniecie=przes
       katobr=obr
       odchylk=odchk
       odchylprze=odchp   
       dlug=0
       pm.spaceLocator(n='pomocnik')

       while(i            aktualnyZnak=self.sprawdzZnak(i)                 
           dlug=self.randomdlugosci(przesuniecie,odchylprze)
           if (aktualnyZnak=='F'):
               self.dodajCylinder(igalezi,dlug)
               pm.parent('konar'+str(igalezi),'pomocnik',relative=True)
               pm.parent('konar'+str(igalezi),world=True)
               pm.delete('pomocnik')
               pm.spaceLocator(n='pomocnik')
               pm.parent('pomocnik','konar'+str(igalezi),relative=True)
               pm.move('pomocnik',0,dlug,0,objectSpace=True)
               pm.parent('pomocnik', world=True)
               igalezi=igalezi+1
               print 'KONAR' 

           elif (aktualnyZnak=='+' or aktualnyZnak=='-' or aktualnyZnak=='^' or aktualnyZnak=='&' or aktualnyZnak=='>' or aktualnyZnak=='                self.obroc(katobr,odchylk,aktualnyZnak)

           elif(aktualnyZnak=='['):
               pX=pm.getAttr('pomocnik.translateX')
               pY=pm.getAttr('pomocnik.translateY')
               pZ=pm.getAttr('pomocnik.translateZ')
               rX=pm.getAttr('pomocnik.rotateX')
               rY=pm.getAttr('pomocnik.rotateY')
               rZ=pm.getAttr('pomocnik.rotateZ')

               doOdlozenia=obiektStos(pX,pY,pZ,rX,rY,rZ)
               self.odlozNaStos(doOdlozenia)
           elif(aktualnyZnak==']'):
               zdjety=self.pobierzZeStosu()
               pm.setAttr('pomocnik.translateX',zdjety[0])
               pm.setAttr('pomocnik.translateY',zdjety[1]) 
               pm.setAttr('pomocnik.translateZ',zdjety[2])
               pm.setAttr('pomocnik.rotateX',zdjety[3])
               pm.setAttr('pomocnik.rotateY',zdjety[4])
               pm.setAttr('pomocnik.rotateZ',zdjety[5]) 

           elif(aktualnyZnak=='L'):
               self.dodajLisc(iliscia)
               pm.parent('lisc'+str(iliscia),'pomocnik',relative=True)
               pm.parent('lisc'+str(iliscia),world=True)
               iliscia=iliscia+1
               print 'LISC'

           elif(aktualnyZnak=='K'):
               self.dodajKwiat(ikwiata)
               pm.parent('kwiat'+str(ikwiata),'pomocnik',relative=True)
               pm.parent('kwiat'+str(ikwiata),world=True)
               ikwiata=ikwiata+1
               print 'KWIAT'

           else:
               print 'INNY ZNAK'

           i=i+1

regulyE=["F[+F]F[-F]F"]
regulyN=["XdrzewoE=GeneratorLSystemuE(3,"F",regulyE)
stringE=drzewoE.GenerujLStringE()
drzewoN=GeneratorLSystemuN(7,"Z",regulyN)
stringN=drzewoN.GenerujLStringN()
parametry=ParametryLSystemu(5,20.5,50,75)
interpretacja=InterpretatorLSystemu(stringN)
interpretacja.interpretujLString(parametry.przesuniecie,parametry.katobrotu,parametry.odchyleniePrzesuniecia,parametry.odchylenieKata)

  • Like 1
Odnośnik do komentarza
Udostępnij na innych stronach

Jak będą wyglądały wygenerowane drzewa pokaże jak skończe skrypt, pewnie po obronie wrzuce go na forum ku miejmy nadzieje uciesze gawiedzi, ale teraz mam drobny problem. Po poczytaniu porad i zastosowaniu sie do nich w houdinim odnalazlem cos takiego:

$(x,y,z) - Rotates the turtle so the up vector is (0,1,0). Points the turtle in the direction of the point (x,y,z). Default behavior is only to orient and not to change the direction.

Wie ktos jak uzyskać cos takiego w pymel ewentualnie python?

Odnośnik do komentarza
Udostępnij na innych stronach

Przepisalem sobie to na maxscript bo nie mam majki i cos tam sie generuje. Ciekawszy wydaje sie GeneratorLSystemuN. Bardzo fajne !!

 

Uwagi mam tylko do kodu ale rozumiem, ze nie jest skonczony ,wiec sie z nimi wstrzymam :)

Mozesz zoptymalizowac na przyklad klase ObiektStos poprzez uzycie __slots__ pythonowych. Znajdziesz opisy w sieci. Trzymam w ObiektStos tylko macierz transformacji przez co zniknelo ze 20 linijek kodu

Edytowane przez CgBartosz
Odnośnik do komentarza
Udostępnij na innych stronach

moje 3 grosze :)

 

zamiast tego:

 

                if self.aks[i]=='F':                   
                   drzewo=drzewo+self.reg[0]
               elif self.aks[i]=='Z':
                   drzewo=drzewo+self.reg[1]
               elif self.aks[i]=='X':
                   drzewo=drzewo+self.reg[2]
               elif self.aks[i]=='C':
                   drzewo=drzewo+self.reg[3]
               elif self.aks[i]=='V':
                   drzewo=drzewo+self.reg[4]
               elif self.aks[i]=='B':    
                   drzewo=drzewo+self.reg[5]
               elif self.aks[i]=='N':              
                   drzewo=drzewo+self.reg[6]
               elif self.aks[i]=='M':              
                   drzewo=drzewo+self.reg[7]
               ...

mozesz zastosowac taki sposob:

 

_dict = {'F':0,'Z':1,'X':2,'C':3,'V':4,'B':5,...}
_index = self._dict[self.aks[i]]
drzewo=drzewo+self.reg[_index]

_dict moze byc atrybutem klasy.

Troche to poprawi czytelnosc kodu.

 

unikaj dodawania stringow w ten sposob:

drzewo = drzewo+ jakisstring

Szczegolnie w petlach moze byc wolo.

Szybciej jest tak:

strinsArr = [str(i) for i in xrange(0,1000)] #list comprehension
drzewo = ''.join(strinsArr)

...takze xrange jest szybsze od range.

 

 

tu zamiast tak:

       if (znak=='+'):        
           pm.rotate ('pomocnik',[kat,0,0],relative=True,objectSpace=True)
       elif (znak=='-'):
           pm.rotate ('pomocnik',[-kat,0,0],relative=True,objectSpace=True)
       elif (znak=='^'):
           pm.rotate ('pomocnik',[0,0,kat],relative=True,objectSpace=True)
       elif (znak=='&'):
           pm.rotate ('pomocnik',[0,0,-kat],relative=True,objectSpace=True)
       elif (znak=='            pm.rotate ('pomocnik',[0,kat,0],relative=True,objectSpace=True)
       elif (znak=='>'):
           pm.rotate ('pomocnik',[0,-kat,0],relative=True,objectSpace=True)   

mozna chyba tak:

def GetVector(_key,_angle):
   _dict = {'+':[_angle,0,0],'-':[-_angle,0,0],
            '^':[0,0,_angle],'&':[0,0,-_angle],
            '':[0,-_angle,0]}
   return _dict[_key]
def RotateNode(_nodeName, _key, _angle, relative=True, objectSpace=True ):
   pm.rotate(_nodeName,GetVector(_key,_angle),relative=relative,objectSpace=objectSpace)

i wywolujesz:

RotateNode('pomocnik', _key, _angle )

 

Nie moglem sie powstrzymac :D

Mam nadzieje, ze to tez troche pomoze w Twojej pracy magisterskiej :)

Edytowane przez CgBartosz
Odnośnik do komentarza
Udostępnij na innych stronach

Na moim kompie takie cos:

 

maxscript i obiekty jako referencje = time:28.808 s

8 iteracji GeneratorLSystemuN.

 

lsysmxs.jpg?w=12ba4dec

 

predkosc juz rozwiazana;) zajmuje okolo 20 sekund w zaleznosci od reguly, teraz robie szlify do mgr i pisze prace, po obronie bedzie dalszy development, dodana bedzie filotaksja itd. teraz same drzewa bedzie generowac pozniej dowolne rosliny.

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się



×
×
  • Dodaj nową pozycję...

Powiadomienie o plikach cookie

Wykorzystujemy cookies. Przeczytaj więcej Polityka prywatności