Wednesday, November 29, 2017

Create an array of planes that fits inside of Camera View using Drivers

This tutorial is based on a question from Blender Stack Exchange user 3pointedit

The main goal is to create a variable count of Plane objects in array (row) that fit in Camera view with additional option for offset space between the objects and the Camera view bounds as well as different coloration of the tiles. Here is a preview of what we are going to create:

This tutorial includes using Custom Properties, Drivers and Compositing and not very complicated mathematical expressions. It is oriented more to the advanced Blender user but I will gladly answer any relevant question left in the comments below.

Warning: Read it slowly to avoid headache :)

If you feel lost - after each main stage you can download a blend file with the current progress.

Let' s Begin!

Start with an empty scene (delete everything). Create a default Plane and rotate it 90 degrees around X axis. Apply Rotation & Scale (Fig. 1).

Figure 1. Create empty scene and add default Plane object aligned to Front view.

Add an Array Modifier with default values.

How Array Modifier's Relative Offset Works and some Math

Let's examine the X value of the Relative Offset parameter (Fig. 2).

Figure 2. Add Array modifier to the Plane.

Value of 1 means no offset from the previous copy.
Value of 2 means the next copy is offset by the width of the original object.
Which means that the offset distance is relative to the object's width and is equal to:

width * (x_off - 1)          (1)

where width is the X dimension of the object,
x_off is the relative offset

width + width * (x_off - 1)          (2)

represents the common width of the object plus the offset distance.

To find the actual width of the object after Array modifier (including the last offset distance) we have to multiply the above equation by the number of copies:

n * (width + width * (x_off - 1))          (3)

where n is number of copies (Count property in Array modifier)

For our task we need to scale back the width of the array object to the initial width size (including the empty space from the last offset distance).

Finding the X scale factor that will bring back the array object to the initial width

We have to find the scale factor that will do the trick. It is simply dividing the original width by the width of the array object:

x_ scale = width / (n * (width + width * (x_off - 1)))          (4)

where x_scale is the scale factor for the X axis

Let's clean up the above equation:

x_ scale = width/(n * width * (1 + (x_off - 1)))          (5)
x_ scale = width/(n * width * (1 + x_off - 1))          (6)
x_ scale = width/(n * width * x_off)          (7)

x_ scale = 1/(n * x_off)          (8)

So, finding the scale factor does not require the width of the object itself

Finding the X location of the center of the array object

Initially the Plane's center (not origin) is located at 0 on the X axis
with each copy the center of the object will move to the right. The relative center of the array object is the width of the Plane multiplied by the number of copies and divided by two

n*width/2          (9)

with the offsets added:

n * (width + width * (x_off - 1))/2          (10)

So we have to move the whole array object back to the left:

width/2 - n * (width + width * (x_off - 1))/2          (10)

Don't forget that we have an offset empty space at the end of the array object so we have to move to the right the half offset distance in order the visible parts to be centered:

width/2 - n * (width + width * (x_off - 1))/2 + width * (x_off - 1)/2          (11)

And because we apply a scale factor to the width of the array object we have to apply the same scale factor (x_scale) to the transformation for the array object:

x_location = (width/2 - n * (width + width * (x_off - 1))/2 + width * (x_off - 1)/2) * x_scale     (12)

where x_location is the new position of the Plane's origin

If we simplify this equation we get

x_location = (1-n)*width*x_off*x_scale/2          (13)

we can further simplify by replacing x_scale with the equation (8)

x_location = (1-n)*width*x_off*(1/(n * x_off)/2           (14)

Finally we get:

x_location = ((1-n)*width)/(2*n)           (15)

effectively solving x_location with two variables

Solving the task


We need three custom properties that will control our Array object:

count - that will control the number of copies
x_offset - that will control the horizontal offset between the copies
z_offset - that will control the vertical offset between the copies

We also need a reference object that will hold an information for the initial dimensions of the Plane and specifically its width. To do that create a linked duplicate of the Plane (Alt+D) move it above and rename it to Reference. Also delete the Array modifier for the Reference object (Fig. 3)

Figure 3. Create linked duplicate of the Plane and name it Reference. Move it up out of the way.

Let's create the custom properties for the Plane.

In Object tab of the Properties editor - go to Custom properties and Add and Edit three properties with the following settings (Fig. 4):

1. count
Property Name: count
Property Value: 1 (note that the value is integer not float)
Min: 1.000
Max: 100.000

2. x_offset
Property Name: x_offset
Property Value: 1.0
Min: 1.000
Max: 2.000

3. z_offset
Property Name: z_offset
Property Value: 0.0
Min: 0.000
Max: 1.000

Figure 4. Add 3 custom properties for the Plane with the given settings.

In Properties Shelf locate and expand  Properties panel for easy access (Fig. 5).

Figure 5. Make sure the Properties shelf is open and the custom properties visible.

You can download the progress so far here:



We will use two methods for adding drivers (Fig. 6):

1. Right click  ( or Ctrl+D) over property - Add Driver - Single from Target - Click with the Picker over Target property
2. Right click  ( or Ctrl+D) over property - Add Driver - Manually Create Later (Single)

Figure 6. This is the usual menu for adding drivers to property.

So let's create the first driver!

Right click over Count property of the Array modifier of the Plane and select Add Driver - Single from Target. Move the Picker over the count custom property of the Plane and click.

Add Graph Editor view to access the drivers channels (Fig. 7)

Figure 7. Create Graph Editor view and open Drivers context view.

Click on the Count channel and go into Drivers tab.
Change the variable name of var to n.
Enter in Expr: field - n
Increase the count value to observe adding new copies to the array (Fig. 8)

Figure 8. Our first driver controls the number of Plane copies.

Similarly, let's add driver for the X value of the Relative Offset of the Array modifier.
Again use Single from Target but this time the Target property is x_offset custom property of the Plane.
Change the variable name var to x_off and type in Expr: x_off. Modify the x_offset value to observe different spacing between the copies (Fig. 9)


Figure 9. The second driver controls the Relative Offset X value.

Go to Object tab, Transform panel and add driver for the X Scale this time use Manually Create Later (Single).
Click on the X scale channel in Graph Editor to view the driver variables.
Rename the variable var to n and change its type to Single Property.
Select Plane object in Prop field and type: ["count"] in Path field
Add another Single Property variable.
Name it x_off.
Select Plane as object and type: ["x_offset"] in Path field.

In Expr field we'll enter the right side of the equation 8:

1/(n * x_off)

Play with the count and x_offset properties and observe how the array keeps the initial width but slightly moves to the right (Fig. 10).

Figure 10. The third driver scales the copies to fit the initial width of the Plane.

To fix that shift let's add driver to X Location of the Plane.

Right click over X value of Location parameter and add Single from Target driver. The target property is count.
Change variable name var to n.
Add second Single Property variable and name it width.
This time as object select Reference and in Path type: dimensions[0].
In Expr: field enter the right side of the equation 15:


If everything is correctly done changing count and x_offset properties will not affect the position and width of the array object while changing the number of copies and the offset between them  (Fig. 11).

Figure 11. The fourth driver moves the Plane object so the whole array stays in place when the user changes the custom properties.

Finally, lets add driver for the vertical offset.
Add single driver from target to the Z Scale value of the Plane object. As target pick z_offset
Rename var to z_off.
Type the expression:

1 - z_off

Changing z_offset custom property will scale the array object vertically (Fig. 12).

Figure 12. The fifth driver controls the vertical scale of the Plane.

Because the drivers update from the custom properties we can change the dimensions of the Plane to our liking.
If we want to fit a Plane to Camera view we need to make the aspect ratio of the Plane dimensions and Camera frame equal.
Lets Add Orthographic Camera to the scene and move it along -Y axis (Fig. 13).

Figure 13. Create Orthographic Camera and place it in front of the Plane.

You'll notice the Resolution is 1920x1080 with aspect ratio of the image 16:9.
You can use any resolution as long as you know how to derive the image aspect ratio from it.
In this case our Plane object must have width to height ratio - 16 : 9.
As we already have Reference object as linked duplicate any vertex editing of the Reference will reflect to the Plane object.

In front view select Reference object, enter Edit mode and scale all vertices along X axis by 1.6, then scale again along Z axis by 0.9. Exit edit mode and the Plane object will update with new dimensions that will correspond to 16 : 9 ratio.

Select Plane object and set all custom properties to default values (just drag the values with the mouse to the left) .Right click Reset to Default Value would not work for the count property and will reset the value to 0 instead of 1, that will cause division by zero error in the drivers. It's a bug - not a feature!

After properties reset go in Camera view and with Plane selected press Space bar and type in search field Camera Fit Frame to Selected (Fig. 14)

Figure 14. Camera Fit Frame to Selected command will do the magic that will fit the Plane into the frame.

This will change the Camera's Orthographic Scale and the Plane will fit completely inside the frame.
Test again the custom properties. The result should be similar to Fig. 15

Figure 15. The final look of the Plane with custom Array modifier which will always fit inside the frame.

With that the drivers set up for the Plane is complete.

You can download the progress so far in the blend file below:


Adding unique colors to the tiles.

As final touch we will add unique color to each tile. This could be useful for selective masking of specific tile by its color.
A quick and easy approach is to take advantage of the color posterization effect.
We will create shadeless material and apply single blend texture to the plane object.
Then we will create a Shader node and with the help of a few Math nodes and custom Color Ramp we will add unique color to each tile.

First with Plane selected create new material and name it Mat_Tiles. Make the material Shadeless.
In Texture tab Create new Texture of Type: Blend
In Colors enable Ramp and change the Alpha of the Black color to 1.
In Mapping set Coordinates to Window (Fig. 16).

Figure 16. The initial settings of the Mat_Tiles material.



In Node Editor switch to Shader type, select Mat_Tiles material and enable Use Nodes. Select Mat_Tiles in Material node (Fig. 17)

Figure 17. The initial look of the Material nodes of Mat_Tiles.

Add the following nodes as shown in Fig. 18

Figure 18. Using some Math nodes and custom Color Ramp we can posterize the gradient of the Blend texture.

Finally we'll add a driver to the Value node to reflect the current number of the tiles defined by the count custom property.
Open Properties Shelf to reveal the custom properties of the Plane add single driver from target and pick the count property.

That's it!

Now whenever you change the number of tiles it will automatically change the number of colors too (Fig. 19).

Figure 19. The last driver will control the number of color posterization steps.

Download the final blend:


Note: Due to the nature of the Window coordinate space - Rendered viewport shading will work correctly only if the camera frame touches the edges of the window (as shown above). The best way to see the result of is to render.

No comments:

Post a Comment