Notifications
Clear all

[Closed] CgTalk Maxscript Challenge 016: "L-Systems!"

CgTalk Maxscript Challenge 016: “L-Systems!”

 DESCRIPTION: Create a tool that utilises an L-System.  This could involve creeping vines, trees, spiderwebs, city creators, anything!  As long as you can think of a creative way to utilise an L-System it's fair game.

 [b]DEADLINE: 03/04/2007[/b]
  
                              RULES:

[ul]
[li]NEW RULE: Do NOT post your code until the deadline![/li][li]Code from scratch. Try not to use pre-exisitng functions or plugins.[/li][li]Show your script references, if any (eg. Looking at another script to assist you).[/li][li]You are encouraged to ask for help where needed, but try to do it on your own. The maxscript reference is an invaluable resource.[/li][li]Post your final script inside [/li]“`
tags (located on your posting toolbar).
[li]Post all code into THIS thread.[/li][li]Post the max version you coded in, plus any maxscript extensions you used. (Thanks galagast!)[/li][li]Try to finish the challenge in a week. There is no definite time limit.[/li][/ul]NOTES: Here’s a link to get you started: http://en.wikipedia.org/wiki/L-system . hint: Start basic!!!

23 Replies

Just some notes on this while i’m trying to work it out myself.

One of the most basic L-Systems is the Lindenmayer Algae formula, where:

A = B
B = AB

(or the other way around…)

Which essentially means if you hit an A branch, make a B branch. A B branch splits into A and B branches, and so the thing keeps growing.

The problem I find comes with array management, as everytime you make a split, you have to increase your growing loop by two. It’s doing my head in a bit working out how to keep the nested loops working, as essentially what I have now is:

[Sketon code]

 for i = 1 to growthSystem.Count do
 (
	for a = 1 to branchCount do
	(
	   if growthSystem[i] = A then drawSpline(A)
	   if growthSystem[i] = B then drawSpline(B)
	   else -- "AB"
	   (
		  drawSpline(A)
		  drawSpline(B)
		  branchCount +=2
	   )
 
	)
 
 )

Obviously this is a little simplified, but I can’t seem to get my code beyond creating the actual system (the easy part!!). It’s been a while since i’ve coded like this, so all discussions are welcome.

Hey Erliaz, that’s a pretty cool challenge, not sure if I have time right now but maybe later. I think I would try something like this to deal with your problem:

 allstuff = #(A,B) 
dostuff = true
while dostuff do
(
for i in allstuff do
(
---here you do the stuff
append allstuff B
append allstuff AB
)
if somecondition do dostuff = false
)

CML

 rdg

The Algorithmic Beauty of Plants can be downloaded here as PDF:
http://algorithmicbotany.org/papers/

I am sure you can find some code snippets in this great book.

Georg

1 Reply
(@erilaz)
Joined: 11 months ago

Posts: 0

Thanks Rivendale, that will probably do the trick!

Great stuff rdg! Thanks. Can you post that link over at the geometrical calculations thread? I’d do it, but I want you to have the kudos!

Hi there, first time participating in this challenges and I’m not much of a math guy but I’ve already did the scripting for two Koch systems and a Bracketed OL System.

I did a different aproach, first I’ve built the string sequence and after that I did it’s visual representation, it seemed more obvious doing that way at the time. I’ll leave here a portion of the code that might help you. I myself I’m having trouble now going into 3D representations, so if anyone already did something it would be nice to share. Cya.


n=0 -- Current iteration
seq="F"-- Axiom
-- Construct L-system string
for n=0 to spn_nmax.value do -- Being spn_nmax.value a spinner for user input on maximum iterations
(
	seqtemp=""
	for i=1 to seq.count do
	(
	 case of
	 (
		 (seq[i]=="F"): -- Represents the predecessor
		 (
			 if n==0 then seqtemp=seq
			 else
			 (
				seqtemp=seqtemp+"F+F-F-F+F" -- Represents the rule
			 )
		 )
		 (seq[i]=="+"): --This stays as is, +-, no rules implied here, they represent right and left turns
		 (
			 seqtemp=seqtemp+"+"
		 )
		 (seq[i]=="-"):
		 (
			 seqtemp=seqtemp+"-"
		 )
	 )
)
seq=seqtemp -- And there you go, you have all your sequence based on user choosen iterations
)

 rdg

I’m having trouble now going into 3D representations

Idea:
After doing the replacement via recursive stringreplacement
we could parse the string letter by letter and point to a differnt function to build the visual representation.

Though I forgot that i token could be build of more than one letter like +F or -F.
Regex could help here, mabye.

Georg

1 Reply
(@erilaz)
Joined: 11 months ago

Posts: 0

This could be done via some kind of turtle code. Check out the Complexity blog: http://www.scriptable.com/blog/complexity/

He’s done a few versions with flash actionscript.

Here’s my progression so far. Right now I think I have the interpretation of the rule wrong, but it’s a start:

WARNING: Don’t increase the iteration value!!!

brAngle = 22.5
brLength= 5
tempLength = 0
START = "F"
rule="FF-[-F+F+F]+[+F-F-F]+FF+[+F-F-F]-[-F+F+F]"
--rule = "F+F--F+F"
anglePos = [0,0,0]
storePos = [0,0,0]
tempPos =[0,0,0]
endBranch  = #(storePos)


fn calcLSystem ruleStr iter = 
(
	tempString = ruleStr
	for i = 1 to iter do
	(
		ruleStrLength = ruleStr.count
		for p = 1 to ruleStrLength do
		(
			if tempString[p]  == "F" then ruleStr = replace ruleStr i 1 ruleStr
		)
	)
	print ruleStr
	ruleStr
)

fn newAngle ang =
(
	theta = ang
	phi = 90 - theta
	
	 x = cos(theta) * brLength
	y = sin(theta) * brLength
	 z = sin(theta) * brLength * cos(phi)
	
	[0,y,0]
)

newSpline = splineShape()
addNewSpline newSpline
addKnot newSpline 1 #smooth #curve storePos
storePos  += [0,0,brLength]
addKnot newSpline 1 #smooth #curve (storePos )

--rule = calcLSystem rule 1
branchCount = endBranch.count
q = 0
while not (q == 24) do
(
	q +=1
	storePos = endBranch[q]
	anglePos = [0,0,0]
	for x = 1 to rule.count do
	(
		case rule[x] of
		(
			"-" : anglePos += newAngle (brAngle*-1) --calculate right
			"+" : anglePos += newAngle (brAngle) --calculate left
	
			"F" : ( --go forward
					newSpline = splineShape()	
					addNewSpline newSpline
					addKnot newSpline 1 #smooth #curve storePos
					storePos  += ([0,0,brLength] + anglePos)
					addKnot newSpline 1 #smooth #curve (storePos )
					brLength/= 1.1
				   )
			"[" : ( --remember branching point
					tempPos = storePos
					tempLength = brLength
				)
			"]" : ( --go back to branching point
					append endBranch storePos
					--branchCount = endBranch.count
					storePos = tempPos
					brLength= tempLength
					
				)
	
		)
		
	)

)



I wish I could participate in these challenges, but I’m not a worthy programmer. I applaude all your guys efforts. I wanted to show you guys a link to an article by a guy who created an ecosystem using proceedural means in houdini. This is an example of taking your guys l-system stuff to the extreme, and I hope it inspires someone out there.

http://www.highend3d.com/articles/references/Ecosystem-simulation-in-Houdini-28.html

Hey Stephen, thanks! And if you’re worried about not doing so well in the challenges, we do the occasional “Back to Basics” challenges which allow people just starting up in Maxscript time to experiment.

1 Reply
(@cyfer)
Joined: 11 months ago

Posts: 0

i’ll be waiting for those ” back to basics” challenges …

Here’s my stuff.

 
(
 
fn laine pointA pointB =
 
(
 
ss = SplineShape pos:pointA
 
addNewSpline ss
 
addKnot ss 1 #corner #line PointA
 
addKnot ss 1 #corner #line PointB
 
updateShape ss
 
ss
 
)
 
-- Koch variant which only uses right angles
 
rollout kochmain1 "Koch 1"
 
(
 
spinner spn_nmax "Iterations:" type:#integer range:[0,100,0] align:#center
 
spinner spn_angle "Angle:" type:#integer range:[1,180,90] align:#center
 
button btn_doit "Do it" align:#center
 
progressBar doit_prog "" align:#center
 
 
 
on btn_doit pressed do
 
(
 
 
 
-- L-System variable related declaration
 
seed(timestamp())
 
t_start=timestamp()
 
doit_prog.value=0
 
 
 
n=0 -- Current iteration
 
seq="F" -- Axiom
 
 
 
-- Construct L-system string
 
for n=0 to spn_nmax.value do
 
(
 
seqtemp=""
 
for i=1 to seq.count do
 
(
 
case of
 
(
 
(seq[i]=="F"):
 
(
 
if n==0 then seqtemp=seq
 
else
 
(
 
seqtemp=seqtemp+"F+F-F-F+F"
 
)
 
)
 
(seq[i]=="+"):
 
(
 
seqtemp=seqtemp+"+"
 
)
 
(seq[i]=="-"):
 
(
 
seqtemp=seqtemp+"-"
 
)
 
)
 
)
 
doit_prog.value = 100.*n/spn_nmax.value
 
seq=seqtemp
 
)
 
t_end=timestamp()
 
print ("L-System string took " + ((t_end - t_start) / 1000.0) as string + " seconds")
 
-- L-system constructed
 
 
 
--Begin visual representation of L-system
 
seed(timestamp())
 
t_start=timestamp()
 
doit_prog.value=0
 
 
 
suspendEditing() -- Disable Modify Panel to make creation faster
 
 
 
delete $Koch1_* --Delete previous Koch geometry
 
length=10
 
angle=spn_angle.value
 
 
 
roda_left=false
 
roda_right=false
 
lx=0 -- Last X Point
 
ly=0 -- Last Y Point
 
lz=0 -- Last Z Point
 
af=0 -- Angle Facing
 
for i=1 to seq.count do
 
(
 
case of
 
(
 
(seq[i]=="F"):
 
(
 
nx=lx+(length*cos(af))
 
ny=ly+(length*sin(af))
 
nz=lz
 
newshape=laine [lx,ly,lz] [nx,ny,nz]
 
select newshape
 
newshape.name=uniquename "Koch1_"
 
newshape.render_displayRenderMesh=true
 
newshape.wirecolor=white
 
lx=nx
 
ly=ny
 
lz=nz
 
roda_left=false
 
roda_right=false
 
)
 
(seq[i]=="+"):
 
(
 
af+=angle
 
roda_left=true;
 
)
 
(seq[i]=="-"):
 
(
 
af-=angle
 
roda_right=true
 
)
 
) 
 
doit_prog.value = 100.*i/seq.count
 
)
 
resumeEditing() -- Enable Modify Panel
 
 
 
clearSelection()
 
max zoomext sel all
 
 
 
t_end=timestamp()
 
print ("L-System graphic took " + ((t_end - t_start) / 1000.0) as string + " seconds")
 
-- End visual representation of L-System
 
-- End Koch
 
)
 
)
 
-- Quadratic Koch island
 
rollout kochmain2 "Koch 2"
 
(
 
spinner spn_nmax "Iterations:" type:#integer range:[0,100,0] align:#center
 
spinner spn_angle "Angle:" type:#integer range:[1,180,90] align:#center
 
button btn_doit "Do it" align:#center
 
progressBar doit_prog "" align:#center
 
 
 
on btn_doit pressed do
 
(
 
 
 
-- L-System variable related declaration
 
seed(timestamp())
 
t_start=timestamp()
 
doit_prog.value=0
 
 
 
n=0 -- Current iteration
 
seq="F-F-F-F" -- Axiom
 
 
 
-- Construct L-system string
 
for n=0 to spn_nmax.value do
 
(
 
seqtemp=""
 
for i=1 to seq.count do
 
(
 
case of
 
(
 
(seq[i]=="F"):
 
(
 
if n==0 then seqtemp=seq
 
else
 
(
 
seqtemp=seqtemp+"F-F+F+FF-F-F+F"
 
)
 
)
 
(seq[i]=="+"):
 
(
 
seqtemp=seqtemp+"+"
 
)
 
(seq[i]=="-"):
 
(
 
seqtemp=seqtemp+"-"
 
)
 
)
 
)
 
doit_prog.value = 100.*n/spn_nmax.value
 
seq=seqtemp
 
)
 
t_end=timestamp()
 
print ("L-System string took " + ((t_end - t_start) / 1000.0) as string + " seconds")
 
-- L-system constructed
 
 
 
--Begin visual representation of L-system
 
seed(timestamp())
 
t_start=timestamp()
 
doit_prog.value=0
 
 
 
suspendEditing() -- Disable Modify Panel to make creation faster
 
 
 
delete $Koch2_* --Delete previous Koch geometry
 
length=10
 
angle=spn_angle.value
 
 
 
roda_left=false
 
roda_right=false
 
lx=0 -- Last X Point
 
ly=0 -- Last Y Point
 
lz=0 -- Last Z Point
 
af=0 -- Angle Facing
 
for i=1 to seq.count do
 
(
 
case of
 
(
 
(seq[i]=="F"):
 
(
 
nx=lx+(length*cos(af))
 
ny=ly+(length*sin(af))
 
nz=lz
 
newshape=laine [lx,ly,lz] [nx,ny,nz]
 
select newshape
 
newshape.name=uniquename "Koch2_"
 
newshape.render_displayRenderMesh=true
 
newshape.wirecolor=white
 
lx=nx
 
ly=ny
 
lz=nz
 
roda_left=false
 
roda_right=false
 
)
 
(seq[i]=="+"):
 
(
 
af+=angle
 
roda_left=true;
 
)
 
(seq[i]=="-"):
 
(
 
af-=angle
 
roda_right=true
 
)
 
) 
 
doit_prog.value = 100.*i/seq.count
 
)
 
resumeEditing() -- Enable Modify Panel
 
 
 
clearSelection()
 
max zoomext sel all
 
 
 
t_end=timestamp()
 
print ("L-System graphic took " + ((t_end - t_start) / 1000.0) as string + " seconds")
 
-- End visual representation of L-System
 
-- End Koch
 
)
 
)
 
-- Bracketed OL System
 
rollout brackmain1 "Bracketed OL System 1"
 
(
 
spinner spn_nmax "Iterations:" type:#integer range:[0,100,0] align:#center
 
spinner spn_angle "Angle:" type:#integer range:[1,180,26] align:#center
 
button btn_doit "Do it" align:#center
 
progressBar doit_prog "" align:#center
 
 
 
on btn_doit pressed do
 
(
 
 
 
-- L-System variable related declaration
 
seed(timestamp())
 
t_start=timestamp()
 
doit_prog.value=0
 
 
 
n=0 -- Current iteration
 
seq="F" -- Axiom
 
 
 
-- Construct L-system string
 
for n=0 to spn_nmax.value do
 
(
 
seqtemp=""
 
for i=1 to seq.count do
 
(
 
case of
 
(
 
(seq[i]=="F"):
 
(
 
if n==0 then seqtemp=seq
 
else
 
(
 
seqtemp=seqtemp+"FF-[-F+F+F]+[+F-F-F]"
 
)
 
)
 
(seq[i]=="+"):
 
(
 
seqtemp=seqtemp+"+"
 
)
 
(seq[i]=="-"):
 
(
 
seqtemp=seqtemp+"-"
 
)
 
(seq[i]=="["):
 
(
 
seqtemp=seqtemp+"["
 
)
 
(seq[i]=="]"):
 
(
 
seqtemp=seqtemp+"]"
 
)
 
)
 
)
 
doit_prog.value = 100.*n/spn_nmax.value
 
seq=seqtemp
 
)
 
t_end=timestamp()
 
print ("L-System string took " + ((t_end - t_start) / 1000.0) as string + " seconds")
 
-- L-system constructed
 
 
 
--Begin visual representation of L-system
 
seed(timestamp())
 
t_start=timestamp()
 
doit_prog.value=0
 
 
 
suspendEditing() -- Disable Modify Panel to make creation faster
 
 
 
delete $Branch1_* --Delete previous Koch geometry
 
length=10
 
angle=spn_angle.value
 
 
 
roda_left=false
 
roda_right=false
 
lx=0 -- Last X Point
 
ly=0 -- Last Y Point
 
lz=0 -- Last Z Point
 
af=90 -- Angle Facing
 
stack_af=#()
 
stack_x=#()
 
stack_y=#()
 
stack_z=#()
 
for i=1 to seq.count do
 
(
 
case of
 
(
 
(seq[i]=="F"):
 
(
 
nx=lx+(length*cos(af))
 
ny=ly+(length*sin(af))
 
nz=lz
 
newshape=laine [lx,ly,lz] [nx,ny,nz]
 
select newshape
 
newshape.name=uniquename "Branch1_"
 
newshape.render_displayRenderMesh=true
 
newshape.wirecolor=white
 
lx=nx
 
ly=ny
 
lz=nz
 
roda_left=false
 
roda_right=false
 
)
 
(seq[i]=="+"):
 
(
 
af+=angle
 
roda_left=true;
 
)
 
(seq[i]=="-"):
 
(
 
af-=angle
 
roda_right=true
 
)
 
(seq[i]=="["):
 
(
 
append stack_af af
 
append stack_x lx
 
append stack_y ly
 
append stack_z lz
 
)
 
(seq[i]=="]"):
 
(
 
af=stack_af[stack_af.count]
 
lx=stack_x[stack_x.count]
 
ly=stack_y[stack_y.count]
 
lz=stack_z[stack_z.count]
 
deleteItem stack_af stack_af.count
 
deleteItem stack_x stack_x.count
 
deleteItem stack_y stack_y.count
 
deleteItem stack_z stack_z.count
 
)
 
) 
 
doit_prog.value = 100.*i/seq.count
 
)
 
resumeEditing() -- Enable Modify Panel
 
 
 
clearSelection()
 
max zoomext sel all
 
 
 
t_end=timestamp()
 
print ("L-System graphic took " + ((t_end - t_start) / 1000.0) as string + " seconds")
 
-- End visual representation of L-System
 
-- End Koch
 
)
 
)
 
 
 
rollout aboutmain1 "About"
 
(
 
label lbl_label1 "by Artur Leão for CGTalk Maxscript Challenge" align:#center
 
hyperlink hl_hp "Artur Leão Portfolio" color:(color 0 0 255) address:"http://dimensao3.com/al" align:#center
 
)
 
try 
 
(
 
closerolloutfloater lsystemsfloater
 
)
 
catch()
 
 
 
lsystemsfloater = NewRolloutFloater "L-Systems" 300 435
 
AddRollout kochmain1 lsystemsfloater
 
AddRollout kochmain2 lsystemsfloater
 
AddRollout brackmain1 lsystemsfloater
 
AddRollout aboutmain1 lsystemsfloater 
 
)
 

Page 1 / 2