This tutorial comes out of an office hours session where we were thinking about how to draw ‘rain’ in Field / AR — a little bit like some of the “particle system” work that we’ve looked at in class.
There are two points to this page. The first is to throw a little bit more example working code at you; but the second is to show how to grow some complex code step-by-step, with each step being fairly easily tested and debugged.
Let’s draw some rain
No, first, let’s check that we can draw anything at all:
Yields
Great. We remember how to draw something.
Next lets consider how we are going to approach this. For rain we’ll need some number of droplets. Since we’re not sure how many let’s make a variable:
I’m sure 20 is wrong, but it seems like a good place to start. Next, let’s have the main structural insight: we’ll need to keep track of the position (at least) of all of the droplets as we animate them over time. Let’s have an array of droplets:
And let’s set them going at a random position:
We had to Google how to add things to Javascript arrays, because we don’t keep that kind of stuff in our heads.
Immediately, we ask did that work? No errors, but let’s check:
Looks like it.
Now we’re short of exactly two things. Some code to draw our droplets and some code to update them.
Yields:
Looks like our vec(0,1,0) is too big. Let’s make it a variable and vary it:
Shorter now:
Ok, so that’s code to draw droplets, now we need some code to update it
If I execute that then I don’t see anything change. I need to execute that and the drawing code over and over to see them move
Perfect! except the rain is going up:
Now, and only now, we’re in a position to put our drawing and updating code inside a _r function which we can call every frame:
Now we have code that randomizes some rain (I couldn’t actually see the rain so I changed num to 200) once and then draws and updates droplets every frame. Of course, it falls forever. Let’s have the rain disappear when it hits the ground and start someplace else:
I also changed the color, because I was still having a hard time seeing it:
Changing num to 1000 and moving the camera around gives us some nice, dense rain:
Extensions
So these droplets are all moving in a rather uniform way. What would I need for these droplets’ motion to be a little bit more organic? The first approach is to carefully deploy random numbers with varying degrees of finesse:
That means that not everything falls at the same speed, but the speed varies every frame for ever droplet — it’s not that some droplets are faster than others in general.
If we want the droplets to have more personality then they need to differ by more than just i — their index. For that we’ll need more storage. Let’s make a second array vel that will hold velocities.
We’re forming a random velocity for each point based on rainDirection and a little random vector vec(Math.random()-0.5,Math.random()-0.5,Math.random()-0.5)* 0.01. What’s with the -0.5? Math.random() yields a number between 0 and 1, so Math.random()-0.5 yields a number between -0.5 and 0.5. Our velocities are equally random left or right.
Increasing that 0.1 yields something that doesn’t look much like rain:
Now that we have a velocity per particle, we’re dangeously close to a high-school physics simulation:
This reads “when the droplet goes under the ground (y<0) move it to the ground and flip it’s downward velocity.
Now we have rain that bounces:
Finally, we remember that acceleration adds a small, downward amount to velocity with every frame:
The stage is set for more complex, “semi-physical” dynamics:
But now our velocity array isn’t really thevelocity any more, and it’s much more exciting if we conspire to draw lines from the droplet position back to where it was in a previous frame. So lets keep track of the ‘previous’ position:
Finally, one last rummage through linear-algebra 101:
Gives (after 30 or 40 attempts!) a particle system following your camera gaze: