1
$\begingroup$

I have a follow-up question regarding my earlier inquiry: Traffic animation with cars along a curve

I want to animate cars driving along a curve and I want the colors of the cars to be random. So I add an Object Info node to the material and connect the Random socket to a Color Ramp node which is in turn then connected to the Base Color socket of the material.

The problem is that when I animate this, some of the cars change color constantly.

My guess would be that this has something to do with the points which are Merged by Distance.

How could I keep the colors randomized yet constant for individual cars ?

enter image description here adding random color to material

$\endgroup$
2
  • $\begingroup$ Your setup feels unecessarily complex. Why would you change the geometry of your curve, where you could simply Sample your curve at any Factor you want ? Do you have a motivation about that or that could change ? $\endgroup$
    – Lutzi
    Commented Jun 28 at 17:07
  • $\begingroup$ This is the result of previous questions on Stack Exchange and I was never able to understand everything what is being done here. So I don't know how it could be done more simple. How would that work? $\endgroup$ Commented Jun 28 at 17:23

1 Answer 1

1
$\begingroup$

Your issue

Everytime you add an object/instance, the Object Info > Random is computed again for all objects. There are at least 2 ways you could avoid that behavior : keep the same cars and teleporting them (looping), or give an attribute to these cars that you'll access from the shader editor.

My setup is a bit bigger than yours, but hopefully you'll understand it and you'll be able to expand it.

Looped animation of cars along curve

Formulation of the process

The process is as follows :

  1. Generate points evenly spaced
  2. Delete some of it according to the traffic density we want
  3. Move the cars along the curve, and when a car reaches the end, we loop it

enter image description here

Because the positions of the cars can be fully described by the curve, we can store the position as a float which will be the distance to the start of the road. When I'll talk about position, I'll refer to this float attribute.

Here is the full node tree. I know it can be scary, but I swear it's not so bad and some of it is similar to yours. I'll go into more detail in the next section

enter image description here

Initial positions

First, we want to increase the curve resolution so that our computations are as precise as possible. I'm setting it to 256 but you could go way higher without any latency. If set too low, cars will be turning by jumps instead of continuously.

Now for the positions, the important part is to get a car on the exact start, and no car for the last segment of the curve. Remember that the end is the same point as the start (which as we just said has a car on it).

enter image description here

We store the length from the start as an Attribute, which means each point has its own position, like a variable.

To get the position for each car, we multiply the index (which is given by default to our points) by the spacing for one car. Let's say the road length is $L$ and the car count is $n$, then the spacing is given to us by : $L/n$.

enter image description here

Traffic density

We randomly delete some of the points, according to the Traffic density input of the modifier.

enter image description here

The random value is giving true/false value based on a probability. We have to invert it (Not) to get the cars to delete instead of the cars to keep.

Computation of positions

To get the next position of a car, we add to its position the car speed we set in the modifier inputs. The speed is actually in meters per frame. It's based on : $x(t) = x_0 + v \cdot t$. In our case the steps are always of the same duration, which simplify to $x(t) = x_0 + v$. That means at each frame, we just have to add the speed to the position.

To loop the cars position, we use a Modulo node so that if it exceeds the end of the road by let's say 3.14m, then we put the car 3.14m after the start.

That's how modulo works, basically you are giving 2 float inputs $A$ and $B$ and asking Blender :

Hey Blender my BFF, if $A>B$, by how much does $A$ exceed $B$ ?

In our case, this is exactly a looping device.

enter image description here

Simulation zone : if you're a bit lost about them, you should know the input to the simulation is only use at frame 1. For all other frames, the input used is actually the output of this simulation zone at the previous frame. It's kind of a loop, one iteration being computed at each frame. So any changes left of the input won't affect anything after frame 1. Here is a visualization of the flow of data. $G(t)$ is the geometry at some frame $t$.

enter image description here

You can also play the animation and change the car speed in real-time. That can be powerful to animate the cars individually (basically with a speed instead of parametric position), but in your case a simple linear animation as you have seems sufficient. Just know that this zone is a door to more complex animations (relying on previous frame's value which is impossible without this zone). See last section.

Set positions & instances

Until this point, each point has its own curveLength attribute (position) but they are all still on the origin. So we sample the curve at their curveLength and we use the Position and Tangent outputs (almost identical to yours).

enter image description here

You can think of the Sample node as asking to Blender.

Hey Blender, what are the curve parameters if I'm looking at this point of the curve, which is from some Length from the start ?

To which Blender will respond

Hello human, well here are the position tangent and normal at that point. But you didn't ask for anything in particular ... Here is an empty Value slot if you want to know about a specific value.

Conclusion and blend file

These nodes already solves your issue, because the points are generated at frame 1 and no point is deleted or added. But ... you could also stored a factor or a color as Attribute, and use it in the shading editor. I don't see a real use-case for you, but sometimes things can't be computed at shader level so that's a really useful way of controlling shaders.

Feel free to ask for precisions if some things aren't clear. If possible, I'll gladly expand my answer accordingly.

enter image description here


Example of variable speed (proof of concept)

You can create more complex and dynamic animations on the speed of cars. Here is a quick example with 2 speeds : when next car is more than 10m away, the car uses double the speed, below 10 it uses the default speed. With a simple rule like that, it already produces a more organic behavior where cars reach an equilibrium :

enter image description here

The nodes are a bit ugly for what they do. But basically :

  • Get the position of next car according to the indexes (with a special attention to loop correctly)
  • Test if greather than 10 (returns 1) or less than 10 (returns 0)
  • Map Range to the default speed and double the speed

It's probably not the best way to achieve this and it could quickly break down if a car goes beyond the next one and indexes are mixed. Take it more as a proof of concept. To be inserted at the very beginning of the Simulation Zone.

enter image description here

The speed attribute should then be called just after that when computing the next position.

$\endgroup$
12
  • $\begingroup$ Wow, this is a very nicely structured answer. Thank you very much Lutzi! I think I need a bit of time to process this and to try to understand. There are still a lot of moments where I'm not able to follow what is happening. I think it would be a good idea for me to follow an extensive tutorial series on Geometry Nodes so I can understand the fundamentals better. Then I will read it again. The point you made about the resolution of the curve is a good one. $\endgroup$ Commented Jun 29 at 16:13
  • $\begingroup$ Is there a way to avoid overlapping of the cars by setting a minimum distance between the points for example? When I now set the cars count on 75 and the traffic density on 0.5 for example, there is a lot of overlapping of cars. See screenshot: imgur.com/a/S0hZnju $\endgroup$ Commented Jun 29 at 16:15
  • $\begingroup$ The car count depends on the length of the road, so I wouldn't recommend setting a limit manually. The spacing (and so the car count) is entirely describe by the length of the road and the size of the cars. It should probably be automatic for a given road curve. $\endgroup$
    – Lutzi
    Commented Jun 29 at 16:26
  • $\begingroup$ Thanks for the clarification. So if I'm understanding it correctly the car count number behaves like the spacing between the cars, but it changes when the length of the road changes. Is there a way to keep the car spacing fixed and independent of the road length? Additionally: if I would want to be able to change the spacing and traffic density on any given frame, would that be possible? $\endgroup$ Commented Jul 1 at 8:00
  • $\begingroup$ Or maybe these 2 things can be solved by giving an an attribute to the different type of cars which I'll access from the shader editor. (As you mentioned in the beginning of your answer.) I have tried to do this on the original file, but I don't manage to have a random color from the color ramp for each type of car (sedan, stationwagon). Screenshot: imgur.com/a/VGd9k59 I have also changed the Blender file in my question to this latest try. $\endgroup$ Commented Jul 1 at 10:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .