Coding Challenge #17: Fractal Trees - Space Colonization

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to one more coding challenge about trees and in this coding challenge I'm going to use an algorithm called space colonization which does not have to do with colonizing space all that would be interesting it's really about colonizing a two-dimensional space of leaves in the screen and you'll see how that makes sense as soon as I start to diagram this out so first I want to mention this algorithm is from a 2007 paper that you can read on algorithmic botany org I'll include a link in this video's description there is also a tutorial that I used in preparation for this from the sea of beans website and I will also which goes through this see this a space colonization algorithm and also include a link to this particular tutorial as well so I'm going to do it in this video it simply in two dimensions in JavaScript that's a processing version that I already made earlier this morning I'm going to program it again from scratch in JavaScript and then in a separate video I'm going to extend the concepts into 3d to see if we can create a tree in three dimensions so first before I start programming it let's just talk about what this algorithm is in a very general way so most of the fractal tree type algorithms that I've done in previous videos or that you may have seen work with this sort of methodology of always growing from the bottom a branch grows from the bottom and it branches and it branches and it branches etc etc etc we saw an l-system is a very similar thing about starting from a point and following these drawing extra instructions to kind of spread yourself out around the screen the way the space colonization works is let's say this is your canvas and you have some volume some little area and you could imagine like creating something sort of tree like like this that is filled with leaves and the leaves are represented as dots so in other words in a way instead of growing from the bottom and reaching the end this algorithm starts with the end like just a random sea of dots those are all the leaves then what happens is you create these segments and each segment is attached to another segment and once the segment once a segment starts to get close to leaves it becomes a track it almost like gravitational attraction to those leaves and we get to tracked it to a leaf it spawns another branch which then as it goes more for our segment which does goes more for it might start to get attracted to another to another branch so you know this is sort of the basic idea and as I start to write the code and get the code for the branches the segments the branch segments and the tree and the leaves going we'll start to see a little more of an itty Gritty of how this algorithm really works they'll come back to this diagram so let's come back over here and I'm going to go to the browser this is a this is what I have so far it's a blank canvas and I'm going to go to my code and all I have right now is set up and draw but I've already created by the way a whole set of other JavaScript files they're empty but I know I want to have a leaf object I want to have a branch object and I want to have a tree object so the first thing I'm going to do is write a constructor function for a tree and in that tree I'm going to have an array of leaves and when you first make a tree I want to create and let's just start with 100 leaves so I need some way of creating all the leaves at first so I'm going to say this dot leaves dot push a new leaf so the very first thing I need to do is just create all those leaves that are going to be in the canvas so I've got that and now in leaf I now want to write a function for a leaf and a leaf is just something with a position so this stop position equals create vector and what I'm going to do actually for simplicity is just make a random location in the canvas so the very first thing I do is I just create a leaf object that has a position vector and the tree object makes an array of a hundred of those leaves and I could also have a function here like this dot show and I could say for all of the leaves draw a of have each leaf leaves index I so to draw the tree draw all the leaves okay so that means now I have to go to the leaf and write a show function and in this show function I'm just going to draw the leaf as a circle at this pause at X this pause Y and you know four by four and maybe the leaf here for simplicity is white and it has no stroke so if I run this particular sketch now I still see nothing why do I see nothing because what I need to do in my main program is I need to say I'm going to actually have a tree and I'm going to make and set up I'm going to make a new tree and then I'm going to say tree dot show okay up leaves is not defined tree is 10 and this is what I forgotten is this dot length and this dot leaves show okay so you can see this is what how I could start I could start with just random leaves now if you how the tree is actually going to look where you place those leaves randomly can really make a difference are they within a box oh they're within a circle or within kind of like a heart shape so there's a lot of possibilities there but this is kind of the basic idea and I'm actually we could see what happens if I create five hundred of them now there's many more leaves in the window so now what I need to do next is create a branch the root of the tree so I need to figure out what goes in this these branch objects so the branch objects if I've been in the wrong place the whole time no the branch objects the branch objects are these little segments and the way that this is going to work or here's an implementation that you could do is you could create a branch object really just only as a position and then when you make a new branch object that new branch object also has a position but it also stores a reference to its parent and if it knows a reference to its parent that segment can always be drawn as a line between its parent and itself so each break each segment is really just also going to be a dot so we're going to start with that so what I'm going to do is I'm going to create a branch object and the branch object is also going to have a position and it's going to have a parent so its parent is another branch so its position is probably something that I'm going to want to get maybe as an X and a Y or even better yet as another as a so as a position and its parent I also want to get as a parent so look at this so I want to create whenever I create a branch I want to give it a position and the parent that's connected to okay so now if I go back to tree in addition to creating a bunch of leaves what I want to also create is the root of the tree so the root of the tree is a new branch and where should it start it can only start anywhere I'm going to weirdly start it in the middle of the window I think that might be interesting and so I need a vector so I'm going to say var position equals create vector in the middle of the canvas with / - height / - and I'm going to make a branch at that position and the root of the tree what's its parent it has no parent so I'm going to just say no so the root is a kind of special case in which that it has no it has no parent so I'm going to have that root and then I also want to have an array of branches and I want to take that root and add it to that array of branches okay now the question oh and you know what I totally forgot something really important so by definition the way that this action algorithm is going to work imagine there are like three leaves here and I have a branch here the branch by definition needs to have a direction a direction that it's pointing because the next branch is the next set and really I should use the word segment the next segment is going to be added at the end and it's going to get a copy of its direction but it's going to get pulled toward the closest leaf which is what's going to cause this kind of meandering of all of these segments so what I need to do in addition is give where am I I need to be in branch each branch needs to have a direction so the direction is also something that I can get from the constructor and so when I make that route I need to and where do I do that entry I need to also give it a direction so I think like the order of my arguments here is a little bit weird I make a new branch at a position and then uh and know is the parent let's go look at that again sorry so position parent let's put the parent first so I'm going to let me come back here and I'm going to say sorry tree branch ah I lost this where am I treat I'm gonna say position null is the parent that's the position and now I also need to give it a direction and I'm just going to arbitrarily have it pointing up so this would make sense especially if I have a root of a tree like pointing up so I want to have that tree pointing up so one thing that I need to do is here's a key there's a key set of there's a key piece of data in this algorithm there's a lot of pieces to this algorithm but key piece of data or something called a minimum distance and a maximum distance and if you read the paper this will be described in the paper the idea here is that later you're going to see that I'm going to be looking at the leaves and I'm going to look at the leaves Leigha Leafs a Leafs distance to various branches very segments that are in the system and belief for it to be relevant has to be between that minimum and maximum distance if it's too far away from any branches it doesn't play a role if it's too close to a branch it's actually been reached and it's done so one thing that I need to do when I start if I only have this single branch I need to make sure that branch is at least within a maximum distance of one of the leaves so the first thing I want to do is add this maximum distance variable and I'm just going to say like a big number for now and a minimum distance and kind of a small number for now so I'm going to say 510 is kind of arbitrary numbers that I'm going to pick what you choose for these values can really affect the system and then what I'm going to do in this tree constructor is I'm going to say okay I made this route and what I want to check is what is the distance oh boy there's a lot going on your p5 vector dot distance between the roots position and any given leaf okay so I need to loop through all of the leaves okay I need to loop through all of the leaves leaves index i dot pause so I need to check the distance between the roots position and the leaves position and if the distance is less than max distance then we've got a branch that's close enough to start doing the algorithm so I want to say var found equals false and then I'm going to say I found equals true and actually what I want to say here is current equals root because what I'm going to do is I'm going to say while not found keep doing this so what I'm going to do here is I'm going to say I want to like check this beginning route like the tree is going to keep growing growing just in a straight direction until it's close to some of those leaves and this you'll actually see in most cases we'll do this later though all the leaves are at the top and the root starts from the bottom so it's just growing straight up until it reaches the leaves and starts to fan out so I start by assuming it's not close enough but if the distance is less than max distance found is true and this while loop should stop but but if if it is not found then I need to make a new branch and how do I make the new branch I can actually take that root branch right remember a branch this is tricky a branch is a position and a direction so what I want to do is get the next branch a next segment attached to it which would be this new position and a copy of that direction so what I can do is bar branch equals and what I want to say is current dot next so why not just have the the branch itself give me the branch that's attached to it so so if I go to the branch I could write a function and this is kind of recursion here in a way next is a function where what does it need to do it needs to make a new branch next branch is a new new branch and where is that new branch so first of all the next branch is its parent is this particular object that's its parent its position is is this particular objects this particular branch is position plus its direction so I need next position equals add this position and this direction so next position and then its direction is just all so this branches direction but I want to be careful about this and so I'm going to make a comment call the copy function because I I want to make a copy of the vector in case various branches change their change their direction the original one should keep their original direction so then I can say return next branch so what am I doing here if I go back to the tree what I'm doing is I'm getting the next branch and then current equals oops current now equals that next branch and I also want to say branches dot push current so this is what I'm going to do now I'm not sure i 100% got this right so I need a way of testing this so first of all let's just run this so branches is not defined so I have some errors so I guess I decided I was going to okay so I can't I can never remember to say this so anytime I refer to branches I need to say this leaves is not defined in line 20 so I need to say this dot leave and this dot leave and cannot read pause of undefined in line 21 whoops back I had forgot a little bit of code in the for loop there so let's take a run this again to see okay so I don't see anything here because I'm not actually drawing those branches so let's go through now and say also for VAR I equals 0 I is less than this branches length I plus plus and what I want to do is say this dot branches index I dot show so I want to draw all the branches so I need to go to the branch object and I also need to add a this show function and now as long as parent is not equal to null so remember all this is only the root doesn't have a parent what I want to draw is a line from this dot position X this stop position not y2 this parent dot position dot X this dot parent da position dot Y so let's make this line white and and so now if I run this again let's see here now let's change this around a little bit what I want to do is actually have the tree start the root start from the bottom and let's actually also have the leaves get a random location that's about a hundred pixels off of the bottom so in this case we should see the branches being attached themselves up until they get within within maximum distance so although maybe the first one is my maximum distance is so high yeah so that worked so you can see here now the this root is going to go all the way up until it gets within a certain number of pixels of one of those branches okay so now once that's done that's the thing so let's just review what we've got so far the only thing we've done so far we come back to this diagram is start with and I'm going to draw this again over to the right we've started with segments that are approaching the leaves and once one of the segment's gets within minimum and maximum distance we need to do something different okay then we stop so we're really just working on getting the root of the tree in place and once we get the root of the tree in place this is where things start to shift instead of working from the branches we're actually going to work from the leaves okay so let me come back over here and now what I want to do in the tree so this is all the stuff that's kind of happening just at the beginning just to get the tree sort of set up and now what I want to do is add a function called grow and the function called grow I want to look at all of the leaves so we're going to go through every single leaf bar I equals 0 I is less than this dot leaves out length I plus plus and I want to look at each leaf so each leaf is this dot leaves index I for every leaf what I want to do is figure out what is its closest branch does it have a closest branch that's in between the minimum and maximum distance so here what I need to do is say VAR j equals 0 j is less than all of the branches dot length and it's this dot branches j plus plus and before I do this I need to figure out a couple things I need to what I what I'm looking for is the closest closest I can't closet closest branch I'm going to assume that to start that there's no closest branch and I also might need the closest direction so the direction of the closest branch but that's in the branch so I don't need to worry about that right now so I'm going to look at every single branch ok so so the main thing I need to do is look for the distance this is really hard this is very long I don't know if this is such a good idea this particular algorithm should have done this in multi parts whatever this is how it's going today ok so what I need to do now I'm looking for the closest branch so I have to find the distance write the P 5 vector distance function gives me the distance between two vectors so I want the distance between the Leafs position and I'm also going to just make a separate variable called branch which is this dot branches index J and that branch is position so a couple things if that distance is between minimum is less than minimum distance so leaves only exists to attract branches toward them once a branch has reached a leaf that leaf is no longer in play so we have to mark that leaf for deletion so I'm going to say lead it's reached leaf dot reached equals true so that means I need to go back to the leaf object and add a variable called reached which is false and we'll use that for something later so the main thing I need to do here in this particular tree I'm in this particular part again okay I'm looking for the closest branch but if I happen to find a branch that's too close that I'm done leaf is reached break and I think I might have when I was doing this earlier I think this might be indication of the bug there was a bug in my code previously and I think maybe this is where it was but we'll find out now otherwise else if distance is greater than max distance then also forget about it this is something to be ignored if it's still greater than max distance forget about it this is a this this particular branch should be ignored actually this no no I shouldn't break because I want to check other branches so I don't need to break I just don't want to include it as anything relevant else if d o else if closest branch is null so if the if it if it's not too far away and there is no closest branch yet guess what it's the closest branch so that means closest branch equals this particular branch and ah what do I need I need a record right that record distance because I want to know if I find another branch that's closer is it even closer so I'll make up some really big number to start with that's kind of ridiculous that's plenty big and then the record is that distance now otherwise last thing else if distance is less than that record right if closest branches not no and it's not greater than the maximum distance if distance is less than that record then guess what we have a new record and a new closest branch so you can notice here that I'm doing the same thing right if it finds something that's null and it's not greater than maximum distance there we go I really think that was the problem my previous code and then otherwise so both of the same thing so I can actually put it over here if you notice like if ever like these two else's do exactly the same thing if it's null or if it's less than record then then this I can I can shorten this so I'm going to do this okay so here we go so this is this whole entire algorithm for every single leaf I'm looking for the branch that's closest to it and it has to be between the minimum distance and the maximum distance so the question now becomes for every leaf after we've looked through all of the branches what do we do what do we do if closest branch is not null that means we found something that means what we need to do is make a new branch with a new direction timeout pause back from a momentary pause I realize there's a very big crucial error in here the thing that I'm checking right I'm trying to find the closest branch and the way that I know I haven't found a closest branch yet is if closest branch is no so this should not be checking if it's not equal to no this should be checking if it's equal to no and I could use 3 equals or 2 equals it's a little bit interchangeable in this spot down here later I'm going to check did I actually find a closest branch so now I have this segmented out if if this particularly is so close to a branch the leaf is done and also this I can also just be safe about this and set closest branch equal to null if it's greater than maximum distance do nothing and if it's between minimum distance and maximum distance then is it actually the record at this point if it's the first one it is the record or if its distance beats the record it is the record okay once we have that we now have we now have our closest branch so when we have the closest branch that we need to do something we need to create a new branch our new segment and let's look at how that works so here I have an existing branch this particular branch and I have this is a an existing leaf and this leaf is the one that's determined to be the close this this branch is closest to this leaf what I need to do is get this as a direction vector normalize it right I want it to be a length one okay well unliving let's not worry about the normalizing it for a second I need to get this as a direction vector essentially I want to add a new segment but I want this leaf to essentially attract it I want it as if this leaf is pulling on the next segment so instead of the next segment just going straight up it goes this way it doesn't go directly to it this is like a force that's pulling it in that direction because here if this continues the next segment is going to pull even more so that an eventual is going to get so close that it'll this leaf will then get deleted so that's why I'm going to get these nice curvy veiny looking paths so how do I pull it a way of pulling it is normalizing it and then adding it to this particular direction and then putting that at the end here so let's look at how I might do that so here with closest branch what I need to do is create a new direction which is subtracting what am i subtracting I'm subtracting that particularly that particularly the closest branches position and then I'm going to normalize it to make it of length 1 just as sort of a generic and I could scale it in different ways you could try different things to play with it but I'm going to normalize it just to to to make it length 1 and then what I'm going to do is create a new branch pause back again after an edit point I did have a problem here this by the way closest branch I meant to set that to null right not true the point is if it's within that minimum distance it doesn't count set closest branch to know now down here what I need to do again I'm back here and back to give is I needed I needed this branch's direction to get pulled towards this particular leaf so what I want to do is say take that closest branch and then I want to take its direction and add this new direction so I use the direction variable way too many times so I'm going to call this a new direction just to be less confusing and I'm taking that existing branch I found the close the branch closest to that leaf I got the direction I found the branch closest to that leaf I found its direction I found that direction and I'm moving its direction toward that the other thing I need to do is the branch then part of this algorithm is actually having the branches have a count variable so the branch needs to count how many times it's been it's been found near one of the particularly use and we are going to see this later because it's going to be immortan because I want to average all of those sort of forces together so what I'm going to do here so I add a count variable and then I say closest branch dot count plus plus okay so let me recap that this is pretty confusing and tricky to see if I can make this make sense I have a particular I have a branch which has a position and it has a direction now I have a bunch of leaves so let's say if I'm going to show you these two leaves so this leaf finds itself closest to this particular branch so what I do is I make a vector that points from here to there I shrink it down and I add it to the direction so now this but this branches Direction is kind of going like this now later I might find this particularly is also close so I need this particular vector and I add it to that it comes back over here so these branch as I go through all the leaves I'm pulling various branches segments that might be close and like stretch I'm stretching them so not stretching them is the wrong word to pen cap went but but but pulling them as if it's a force okay so this this is now done right this this part of the algorithm is done I'm looking at every single leaf the leaf if it's less than minimum distance from from a branch up for every leaf I look at every single branch if it's too close to a branch we're done with that leaf if it's too far away from the branch it's not a can't that branch is not a candidate if it actually is the closest one I'm going to keep track of it and that branch is going to be attracted to that particularly so once I've done that now it's our job to do the following the first is I need to go through and find any leaves that were too close and delete them so I'm going to loop through and I'm going to I'm going to loop through the leaf array backwards because at what deleting things from an array you need to loop through it backwards because you're taking stuff off the end let's not mess it up so I starts at the end of the array goes down to zero and then I - - so and I'm going to say if this dot leaves index I was reached remember I have in the leaf in the leaf object I have a reached variable at set to false and what do I do in the tree if it's within the minimum distance I set that reach to true so then later I can go through in a separate loop I could have done it in the loop above but just for simplicity I'm doing this in a separate loop I can then say this dot leaves splice delete one element from the array at index I so that's the first thing I can take care of the next thing I can take care of is I need to go through all of the given branches so now I need to look at every single branch and I need to figure out what branches were were attracted to what leaves so how do I know if a branch was attracted to a leaf well I know if it's count was increased by at least one so branches could be attacked in two leaves zero one or more times and I only care and I'm going to save our branch equals this branch's index I just to make my code a little easier to work with I only care about branches whose count is greater than zero and if their count is greater than zero what I need to do is make a new branch attached to it so how do I do that so the first thing I need to do is I need to actually average I need to divide by count because I was adding all those vectors to it and if it was near ten ten different leaves then I want to divide by ten so what I should do is take that branch that branches direction and divide it by that branches count so that's a way of averaging however many branches I was sort of attracted with a force and then I want to make a new branch so if I make a new branch I always need three things I need I need the branches parent the new branches parent is that existing branch then I need the branches position which is that branches oh the parents position plus the bat branches direction so a new position equals create equals add add the previous branches position with that branches direction and that's the new position and then also the direction and I'm going to copy it now I have some redundancy here because honestly if if I am I could actually write a function in the branch object to produce the next branch and I did that actually in a previous processing version of this that I didn't but right now this is where we can see what's going on here I have to make a new branch right that this is a it's growing its parent is the previous one it gets a new position based on that new direction and also it's got a store that direction in case it connects to it starts being pulled towards leaves as well and then I should just be able to say branches this branches dot push new branch well someone's telling me line 66 I forgot to add thank you so this should add those two thank you very much yeah okay so so let's I think that's kind of everything this is the grow this funk this is the grow function let's just run this and see if I have any syntax errors so this still looks about right but I didn't actually call the grow function I'm a little bit afraid to I added a ton of code I'm gonna add that grow function now and draw hmm I don't see anything happening okay so we got to figure out what am I missing here at least I'm not getting any syntax errors let's first at least see if grow is not isn't there might be getting stuck in an infinite loop somewhere so in the tree function I'm going to just console.log growing so let me just make sure this is getting called over and over again okay so I'm not stuck things are looping oh the count has to be reset so I forgot something very important each generation I've got a reset I've got to reset the count and also actually the branch should have its original direction it shouldn't change so this is great I forgot an important step no wonder it's I don't know if this is what's causing the problem but I certainly did it forget a really important step so branches have to be reset so what one thing I want to do is say original direction equals so I always want to keep a copy of the branches original direction because after a branches Direction gets manipulated in order to in order to create the direction of the next branch I knew I forgot something I need its direction to go back and I need to copy it again so I need to restore its direction I go I could probably after I do this I could probably go through the code and find if extra places where I copied vectors but I have to be very careful that I don't by accident have vectors pointing to the same data changing one place it changes into another place and I also need to reset count by zero so what I need to do is after at the very end here when I go through all of the branches I need to once again and I should go through the branches this is bad by the way I'm surprised that this didn't cause a major major problem because I'm going through this array of branches and adding to the end so here I also want to start at the end of the array and go backwards down to zero and and then add to the end and I can also if and I know just for safety I can reset all of the branches so this is definitely something that I missed what I need to do is as I'm going through the branches to create to throw the ones that were close to leaves to create the next branch I create the next branch and then reset that branch and so now okay original dir is not defined where is that in branch judge as line 9 of so this by the way to say this dot dir actually kind of work because that's there and then this also needs to say this dot originally okay so promising this is all still growing so what did I miss okay so so let me look here in tree and see why things might have gone wrong so let's just see is this actually happening am i finding things I'm not finding any closest branches now I wonder if there's an issue with my just my like Oh maximum distance being the same as minimum distance that can't be good how did I how did I do that by accident there we go something crazy is happening okay so that kind of worked I think maybe my distance was too short something this is kind of doing stuff now hey I like how this works okay it's working now we're getting a nice little tree growing and branches being attracted to leaves and things being spread out you can see how it's working I think this is kind of about right so there's a couple things that I notice like it's actually running quite slow and something I could do to kind of speed things along that makes more sense is also to to have the branches have kind of a minimum length if you might the length is based on the direction vector which I didn't actually normalize I just realized I think I think there's some like technically some correct way of doing this that I probably missed so if I go here when I made the new direction um let me find that where is that oh I already had this next function look at that I forgot that I have the next function so that this is actually could be I should what one thing I could do to improve this I got this now sorry back where is that in the tree I don't actually need to do this here I should be able to just say this dot branches dot push new branch dot next so I should be able to use the next function which just gives me that next that next branch based on that so that I should be able to use this should be identical so that saves me that's I have that next function I should use that and the reason why I thought back to use that is because I should just do this entire video again because I understand this algorithm so much more now from having to like be in this very awkward place of programming it live but what I want to do here is go back to that next function and what I can actually do is I can say I'm going to make a I'm going to multiply this dot Direction times 5 right so this is kind of like the length and you know I can actually give this a length so branches can have a sort of default length and then I can add that so if I do that I know I did that kind of quickly but what you'll see here is like it's kind of growing much faster now because each branch by definition moves by five and I wonder if actually this should always be normalized I don't know if that really makes a difference I think it's the same I think by definition because I divided by count it might have been that's sort of like normalizing it but anyway so this is pretty good so I'm going to stop here I guess I'm going to do so I'm gonna I'm gonna go back to this algorithm and look at it in 3d and maybe but here's the thing so I'm gonna post this code it'll be linked in the description of this particular book incredibly long video i don't know i just like 45 minutes long but really what you want it what i want you if you've watched this if you've stayed with this if you're working with this code what what um should um what you somebody the chat oliver and the chat has made an excellent point which I'm going to fix before I go on but what I want you to do is think about how are you arranging those seed leaves what is your minimum distance what is your maximum distance what is your length of each branch so what types of patterns leaf vanie tree like patterns even in 2d how could you use color you know how can you use thickness the more branches that are layered in the same spot can you make it Aker try some of these ideas improve on this and I'll try to come back in another video and kind of make these improvements because I think it would be good to do a follow-up on this but let me just fix one thing I don't need to normalize the direction because I divided by count but where did I divide by count I divided by count here but I really should be dividing by count plus one because I'm also including the original direction vector which is a unit vector so I've added that unit vector with all the other unit vectors of close leaves and so there's one more there so I should so that should probably make things more quote-unquote correct and you can see how this works so I'm just sort of curious just to play with this for a minute here like for example entry what if I give myself only 50 leaves you can see kind of what I get there with only 50 leaves what if I give myself 1500 leaves you can see what's happening with 1500 leaves and you can see some are getting kind of like a lot some of these like perfectly equidistant ones or getting ignored like the branches just go right through the middle of them which is kind of interesting but really what be more interesting would be for me to arrange the beginning okay I have to end this video now I'm going to move over to processing in the next video and look at the same algorithm and try to extend it into 3d and at some point I might come back and try to do that in JavaScript in 3d as well okay thanks for watching
Info
Channel: The Coding Train
Views: 108,859
Rating: undefined out of 5
Keywords: space, coding, challenge, patreon, processing, daniel shiffman, p5.js, processing tutorial, nature of code, tutorial, p5js, coding challenge, object oriented programming, creative coding, programming challenge, p5.js tutorial, object oriented, oop, javascript (programming language), simulation, space colonization, space colonization algorithm, algorithmic botany
Id: kKT0v3qhIQY
Channel Id: undefined
Length: 45min 52sec (2752 seconds)
Published: Tue May 31 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.