Friday, April 1, 2016

Getting Started with ZBrush - For Rhino Users

This post contains the basic information you need to know to begin sculpting with ZBrush. This post is specifically for Rhino users who want to import and sculpt models, then export them as meshes back into Rhino. There are a many tutorials online, but sorting through what's important and reviewing the material can be time consuming. This post is a concise subset of the tools to get you going quickly.

If you work your way through this post you'll be able to do quite a bit in ZBrush. At the end I'll point you to more tutorials to further help you develop your skills.

The ZBrush User Interface

When you first look at the ZBrush user interface it may seem different/complex/confusing. It is different. And it may be complex. But it does not need to be confusing. In fact, you can do quite a bit of detailed sculpting with only a few tools. The user interface is tuned for artists and designers. The workflow in using the program is really excellent and once you get comfortable it it fades into the background. You feel you are sculpting clay rather than interacting with a computer program. So don't be put off by the uniqueness of the UI. It is well worth diving into!

Creating a First Object to Sculpt On

When you first start ZBrush a dialog appears across the top of the screen. This is the LightBox. You can think of it as an asset browser. By assets I mean, objects, textures, materials, brushes, etc. You can use LightBox to quickly load an object to sculpt on. Double-click one of the spheres shown - I'd suggest DefaultDynaWax64.

This replaces the current file with a new sphere, at 64,000 polygons, using a wax material. We'll sculpt this very shortly!

For experience CAD users it may seem strange but ZBrush does not deal in conventional drawing units (inches, mm, etc). Everything is visual - you work by eye. When you finish a model you can scale it to size before exporting it. But inside ZBrush forget about units and drawing with typed coordinate precision. Just sculpt visually and enjoy the freedom.

File Opening / Saving

Working with files is pretty much as expected. To save a project use the File > Save As button. To open a project use the File > Open button.

When you need to start a new document use the Document > New Document button. This will clear the canvas and let you start over.

You can also use LightBox to browse for files to open.

Viewport Navigation

The first thing you need to learn to do is manipulate the viewport; Rotate, Pan and Zoom the view of your model.
  • Rotate: Left-click in an open area (where there isn't an object to sculpt), then drag. The view will rotate. Note: You can hold the Shift-key when you rotate the view. Doing so will snap the model into Front, Back, Left Side, Right Side, Top and Bottom alignments. 
  • Pan: Hold the Alt-key and left-click and drag. The view moves laterally. 
  • Zoom: Follow this sequence: 1) Hold the Alt-key, 2) Left-click and hold, 3) Release the Alt-key, 4) Drag. This zooms in and out. You have to keep the left click held as you release the Alt-key. 
These may seem strange at first (especially Zoom!), but once you get used to them they become quite natural and fluid. So spend some time early practicing these and getting comfortable.

You can press the F key to "Zoom Extents". You can press Shift+F to toggle wireframe display on and off. And don't forget using Shift with rotate to lock into the orthogonal views.

Common and Useful Sculpting Tools

The choice of which brushes to use in ZBrush is key to effective sculpting. When you click the Brush icon you are presented with a large palette of loaded brushes:

There are many to choose from but you can do a great deal with just a few. Before you can use the brushes effectively there are a few controls you need to be aware of and adjust as you work the brushes. A convenient way to access these controls is by pressing the Spacebar. This menu appears:

These most important control in here are:
  • Draw Size: Sets the size of all brush strokes or editing actions. The draw size is shown as the outer circle when you hover over your sculpt. Adjust this often - making the brush the proper size is key to getting good results. 
  • Focal Shift: This shifts the affect of the tool closer to the center or away from the center. This size is shown as the inner circle. 
  • Z Intensity: Sets the amount of depth information of the current tool. The higher the intensity the greater the effect of the sculpting tool. If you find the tool is too sensitive (particularly on low resolution models) turn this way down. 
With those settings understood you can get to sculpting. Here are the most common brushes I work with. Try them out on the sphere you loaded as you read about them below. 

Move Topological: Moves vertices on the mesh around without affecting those not directly attached to the brush area. Coupled with sizing the brush and focal shift I use this all the time to adjust the sculpt.

Clay Buildup: Very useful for building up layers of virtual clay. This brush will fill in low areas before it builds up higher area. This is kind of like smoothing clay onto the surface - it'll squish into the recesses first. As you stroke back and forth it'll build up. The alpha channel is used so it gives good control of how the stroke falls off. Note: You can hold the Alt-key to reverse the effect and have the tool push into the surface rather than build out from it.

Smooth: Takes a rough surface and smooths it out by averaging the level of the surface. I usually turn the intensity way down to make the effect more controllable. Important Note: Simply press the Shift-key to activate this mode. You don't need to change tools to do so.

Inflate: Expands an area of the sculpt by pushing vertices along their normals. Great for adding volume to a feature which is too small. It can also be used to deflate - pushing the sculpt in the opposite direction. The Alt-key works here to invert the effect.

Slash3: This brush is used to cut into a surface to create a tight crease or slash. I find the default intensity too high so consider turning it down. The brush size has an important impact on this brush's effect so experiment with the size as well. As usual you can hold the Alt-key to pull out a "slash" stroke.

Pinch: This brush pulls vertices together effectively pinching the surface along your stroke. The brush optionally allows the verts to be pulled up or pushed down.

You can accomplish a lot of sculpting with just those brushes. I think it's interesting to note that these are the tools available in Sculptris (the simpler, free version of ZBrush).


Alphas are grayscale images used to control the deformation of the mesh as you draw out brushstrokes. The brightness of the alpha determines the low areas versus high areas. Dark areas in the image deform the mesh less than bright areas which deform it to the full Z Intensity.

Experiment with a few alphas and you'll quickly get a feel for this.


The stroke controls how the mouse or stylus applies the effect of the brush to the sculpt. For example there is a stroke which acts like spray paint. For most use you'll want the Dots or FreeHand stroke active. If you are using alphas to apply detail to your mesh you may want the DragRect stroke. This lets you drag out a rectangular area and the alpha gets applied in that area like a decal.

Experiment with these to test their effect on the mesh.

Note: At times you may find that the back side of a mesh is being deformed by a brush. In thin areas of the sculpt this can happen. Here's an example - the front is sculpted. But the back is pulled forward as well:

You can prevent this by enabling the AutoMasking / BackfaceMask button. This is a setting in the Brush menu:

Now when you apply that stroke the faces facing away are unaffected:


It's sometimes desirable to want to work symmetrically. Changes to one side of the objects are mirrored to the other side.

The most common symmetry is easily toggled using the X key. This mirrors about the X axis of the model. For more detailed control of symmetry open the Transform pull-down menu and work with the controls in the Activate Symmetry area:

You can have X, Y, and Z on in any combination. You can also click the (R) button to toggle Radial symmetry and set the RadialCount. Try it - it's lots of fun :)


This features lets you sculpt away without having to worry about your underlying geometry. You can stretch, pull and manipulate the sculpt in any way you choose. If it becomes too stretched out or low resolution in spots, simply re-dynamesh.

If you started with the DefaultDynaWax64 model then Dynamesh is already on. If not, you can easily turn it on. This feature is in the Geometry panel, in the Dynamesh tab:

Using the Resolution slider you set the number of polygons you desire (in K). So 64 means approximately 64,000 polygons in the regenerated model. If you set the Polish button on the mesh will be smoothed during the remeshing. Then press the DynaMesh button. This will regenerate the model. You only need to press the button once. It stays lit up in orange.

Once DynaMesh is on you simple hold the Ctrl-key then drag downward in an open area of the viewport. This action gives you a newly generated mesh with an even polygon distribution. Do this whenever you feel the mesh is stretched or the topology isn't looking smooth or uniform.

Before - modifications have really stretched the mesh topology:

After - no problem! Ctrl+drag = Fixed:


Masking is a powerful tool to limit the area of the sculpt that's affected by the brush. To create a mask hold the Ctrl key and "paint" with the brush. The Draw Size and Focal Shift settings apply to masking so set those properly. Masked areas will turn dark gray. If you brush over these areas they remain unaffected by the tool.

The mask usually falls off near the edge so the effect of the mask is softened.

You can hold the Ctrl-key and tap on the mask area to further the softening of the mask. This makes the transition from masked to unmasked even smoother.

You can hold Ctrl+Alt and tap on the mask area to make it tighter:

You can Ctrl+click in an open area of the viewport to invert the mask.

Getting Ready to Export to Rhino

ZBrush supports very high resolution meshes. If you try to export these to Rhino you'll likely overwhelm it! Therefore you need to use the decimation tools to reduce the mesh complexity without dramatically compromising the form. ZBrush has some great tools for this.

Decimation Methods

Decimation refers to rebuilding the mesh with a lower vertex/face count. There are three ways to do this:
  • Dynamesh (discussed above): Nearly instantly regenerate the topology of your mesh with a controlled resolution. But because it is so fast, the topology generated is not as refined as the other methods. For final export use the next two methods. 
  • Decimation Master: This is a plug-in which lets you rapidly experiment with different mesh polygon counts. You pre-process the model once, then you can quickly test out different resolutions of the mesh to get it to your liking. This tool does a remarkably good job. 
  • ZRemesher: This tool lets you create a new polygonal model of your sculpt where you can specify a count of the number of polygons. It quickly retopologizes the model in a manner that follows the surface in a natural way. This method is the slowest, but produces the best results. You also have control over the topology (areas of higher and lower detail) as well as some control over how the edge loops flow. That is not possible in the other methods. So for best results use this method. 

Decimation Master

This is the original plug-in to reduce mesh complexity while maintaining the overall form. It still has advantages, mainly speed in getting results and exploring different mesh resolution settings.

It's available from the pull-down menus: Zplugin > Decimation Master. The interface is shown below:

After you click the UI often disappears. So you have to bring it up repeatedly from the pull-down menus. (Yeah I don't know why either... anyway...)  The process to use it is very simple. First, press the Pre-process All button. This will take a little time as it generates a file to allow you to quickly decimate in the future. A progress bar scrolls across the top of the screen. Once it's done set the number of polygons you desire with the k Polys slider. For example if you want to decimate to 20,000 polygons set the slider to 20. Then press the Decimate All button. ZBrush will rapidly regenerate the model with the desired resolution and the viewport will update. If you are happy with the result you can save the model. If not, bring up the UI again and try a different value and press Decimate All again.

You can also set the % of decimation slider. So 10% will make it much smaller, 90% will only reduce it a little.

It's as easy as that, and the results are really good.


This is the latest technology from Pixologic. It's easy, fast, and does a amazing job. It's also controllable. You can use Polypaint to control the tesselation adding more detail in areas and less in others. You can also use what are called ZRemesherGuides to control the flow in ZRemesher.

You get to it in the Geometry panel under ZRemesher. Here's the UI:

The simplest thing to do is enter a value in the Target Polygons Count slider. 5 is 5,000 polygons. Then press the ZRemesher button. It takes a little time, the progress bar along the top shows the status. When done the model is remeshed.

Extra control is provided by PolyPaint. Enable the Use Polypaint button. Then adjust the ColorDensity slider to paint on specific areas. How PolyPaint affects the density is determined by the color used:

  • Red specifies a higher polygon density within the painted area.
  • Blue specifies a lower polygon density within the painted area.
  • White (no PolyPaint) gives ZRemesher total control over polygon density.

A ColorDensity setting of 2 doubles the polygon density. A a setting of 0.50 halves the density.

You can also use the ZRemesherGuide brush to draw curves on the model which guide the remeshing. This only works if you turn the Curve Strength slider quite high (near 100). Otherwise the normal algorithm takes precedence.

The written documentation is here. Also, this video covers the other controls quite nicely.

Sizing the Model for Export then Exporting

Assuming you have decimated your mesh you are now nearly ready to export. But what about the size of the model? ZBrush doesn't deal with conventional modeling units of feet, meters, etc. However, when you get ready to export your model you can set a size that will be correct on export. You do this Zplugin pull-down menu. Then open the 3D Print Exporter panel:

Here you set if you want to export in inches or millimeters. You set one of the X, Y or Z size sliders then press the Update Size Ratios button. This will update the other two to keep the proportions the same. For a sculpt at building scale this notion of inches or mm is kind of small! However, you can easily scale up in Rhino so it's no problem.

Once the size is to your liking you press the STL, VRML, or OBJ buttons to export to that format. Rhino will import all of these formats so you may choose whichever you like.

Importing Rhino Models into ZBrush

Importing into ZBrush means exporting out of Rhino. So let's start there. In Rhino use the File > SaveAs... command.  Use OBJ as the file format. The next image shows the settings to use - underlined are key ones:

You want a polygon mesh, you want the vertices welded, and you want to swap Z and Y. Rhino uses Z up and ZBrush uses Y up. That settings keeps the orientation the same between the two programs.

Inside ZBrush you use the Import button on the Tool palette to bring in your model. After you import you'll have a new tool which is your mesh. You can select that tool and drag it onto the canvas. If you are starting a new document be sure to immediately press the Edit button (or press the T key). This puts you in edit mode so you can use the sculpting brushes to manipulate your model.

Further Learning - Video Tutorials

The following tutorials are also very helpful in developing your ZBrush skills.

First, the ZClassroom has a large library of very well put together, succinct videos.

For hard-edge modeling a fantastic tool is the ZModeler Brush using QMesh. Here's a video on the basics of it's use - be sure to check it out: Poly QMesh. Another video on the ZModeler Brush is more detailed and proceeds at a faster pace. It's really good. If the first one captured your interest be sure to check this one out.

Tuesday, March 29, 2016

Working with Planes in Kuka | prc

Kuka | prc is a method of driving Kuka robots using Grasshopper. This topic describes the use of planes when programming robot motion. (The larger topic of programming using Kuka|prc is here.)

You can think of a plane as an origin (location in space) and an orientation for the X, Y and Z axes (rotational direction of the axes). Planes are drawn in Grasshopper as a tiny grid, with the X and Y axes shown. You control the display size using the Grasshopper pull-down menu option Display > Preview Plane Size, then enter a size in model units.

You can create a Plane component in Grasshopper then right-click on it and choose Set one Plane. You are first asked to set the origin then asked to define the location of the X axis, then the Y axis. Note that once you define X and Y, then Z is defined automatically, perpendicular to X and Y, using the right-hand rule.

Planes are what are fed into the motion commands to move the robot. The plane specifies the location of the Tool Center Point (TCP) and the orientation for the robot face plate. So an understanding of them is essential to using Kuka | prc.

Generating Planes from Geometry

Planes drive the motion of the robot. Since we often want to follow geometry we've modeled or generated algorithmically in Grasshopper, there are a number of easy to use component which generate planes from geometry.

A simple example is creating planes to cause the robot to follow a curve. The Divide Curve component can be used to output points at equal intervals along the curve.

The planes appear in the viewport like this:

Note that these planes all have the exact same orientation. That's because the points were wired into a World XY component which set the constant orientation to match world XY. This is fine is the tool doesn't need to rotate along the curve.

It's also possible to generate the planes so they oriented tangent or perpendicular to a curve. To do so use the Horizontal Frames component.

The resulting planes. The X axis is tangent to the curve.

This can be used when you want the tool to rotate along the curve. For example if the tool was a knife cutter it needs to follow along tangent to the curve at all times.

It's also possible to generate frames which are perpendicular to the axis along the curve. To do so use the Perp Frames component.

The resulting frames:


There are a number of useful Grasshopper components for dealing with planes, available in the Vector menu / Plane panel.

XY Plane, XZ Plane, YZ Plane

These components output planes matching the world XY, XZ and YZ coordinate systems all centered on the origin. You may wire in a different origin to move them around.

If you right-click on the origin socket and choose Extract Parameter Grasshopper wire in a Point component. You can then enable Gumballs in Grasshopper menus (Display > Gumballs). When you select the Point component you can use a small Gumball widget to graphically alter the point. Doing so interactively adjusts the robot position in the viewport.

Unit X, Unit Y, Unit Z

Also handy are the built in unit vectors for X, Y and Z. These are available in the Vector menu / Vector panel. You can wire in scale factors to change the magnitude of the vectors, or negative values to change their direction and magnitude.

Construct Plane

This component lets you construct planes by specifying an origin, and separate X, Y, and Z vectors to define the plane. See the image below under Deconstruct plane for an example in use.

Deconstruct Plane

This component lets you deconstruct a plane by breaking it into an origin and separate XYZ vectors. The example shown below uses both Construct and Deconstruct; you can see an origin point is wired into Construct Plane on the left (1.0 2.0 3.0). Also wired in are the standard X and Y vectors. This builds a plane, centered at world 1, 2, 3 aligned with the world XY plane.

The plane is then Deconstructed to show they match. So the origin output is 1, 2, 3. The X vector is in fact 1, 0, 0 and Y is 0, 1, 0. Z is, as expected, 0, 0, 1.

Alter Plane

This component is very useful in re-orienting one of the standard planes. For example you can flip the Z axis of the plane to point in the opposite direction. Here you see a -1 factor wired into a Z vector which is wired into the normal of the Alter Plane. This flips +Z so it aligns with world -Z (down).

Note too how this example divides a curve up to generate the various origin points for the plane. You can see a list is output from Divide Curve. That's wired into the origin of the World XY plane.

Cross Product

Given two vectors this will output a new vector which is perpendicular to both those wired in. In the example below unit X and unit Y vectors are wired in. The output is unit Z (0, 0, 1) which, of course, is perpendicular to X and Y. 

Monday, March 28, 2016

Data Matching and Data Trees in Grasshopper

An understanding of data matching and data trees is critical to successfully developing more complicated definitions in Grasshopper. This post will help you understand these concepts.
The Grasshopper examples (and corresponding Rhino file) shown below can be downloaded here. You can disable all the components in the definition, then Enable those in a single group to see its effect.

Data in Grasshopper

Data in Grasshopper can be single values, lists of values, or what are known as trees of data.

Single Value

A single value is obvious, for example the output of a number slider is single value. You can see this when you wire it into a panel:

You can also see this in the wire itself - it is shown as single solid line which indicates a single value.

Here's another example. The single value is fed into the radius of a Circle component. A single plane specifies the plane to draw the circle on. The result is one circle drawn.

List of Values

A list of values results when a component outputs several values. An example is the Series component which outputs, well, a series of numbers. The user specifies a start value, and an increment for one value to the next, and a total count of values. In the example below the series starts at 1, is incremented by 2, with a total number of values of 3.

The Panel shows the output values, 1, 3, 5. Also note the wire is shown as double lines indicating the data is a list rather than a single value. The Series is wired into a Circle component which uses the value as a Radius. The result is three circles of radius 1, 3, and 5.

There are some components commonly used with lists. List Item returns a single item in the list. List Length returns the number of items in the list. Usage of these is shown below:

Tree of Data

A tree of data is output when a hierarchy is involved in the data. It's called a tree because the data is organized into separate branches. A simple example is when you use the Rectangular component to create a grid of cells/points, each column in the grid is in an independent branch. In the rectangular grid below there are 4 columns and 6 rows. The tree has four branches (one for each column). In each branch is a list of 6 items. A circle is drawn at every point. 

Grasshopper provides tools to help you visualize data trees. First, note the wire coming out of the grid is drawn as a dashed line. That always means the data is in the form of a tree. There is a component called the Param Viewer which lets you visualize the structure of the tree.

The Param Viewer shows there are 4 branches, where each one has 6 elements (N=6). The Param Viewer has a right-click menu option to draw the tree graphically.

With that enabled you see a graphic representation of the tree. Note it only shows the 4 branches, not the "leaves" (the list of 6 items in each branch).

Another tool useful in visualizing a tree like this is the Point List component. When there is a tree or a list of points, Point List labels them in the Rhino viewport by using numeric text to show the position in the list of each point. Here it is wired in, with a slider to set the text size, shown in Grasshopper and the viewport.

It's very important to note the following; There are four branches, each with six points. The Point List shows quite clearly that each branch is independent of the others. The points in each branch are labelled 0 to 5. Then the numbering starts over again at 0 again. Why? Because each branch of the tree is independent of the others. The data is not shared between or across branches. Therefore the Point List shows them independent of one another.

This independence of the branches is usually very useful. It can also be controlled by using specialized components to manipulate the branch structure. Your skill in using these components has a big impact on your overall skill with Grasshopper in general.

There are some common components used with data trees. These are Flatten and Graft. Have a look at the Param Viewer examples below to see the structure of each tree after being processed by Flatten and Graft.

This component converts the data from a tree into a list. It removes the hierarchy information entirely. The grid point labeling, after flattening, looks like this:

As you can see the hierarchy is gone and the points are numbered in order, 0-23.

This component takes every leaf in the tree and makes it its own branch. Since the branches are independent, the point list is all 0's. That's because as soon as it labels one point it starts a new branch and the labels its first point. There's always one per branch.

Flip Matrix
This component flips a "matrix-like" (think two dimensional grid or array) data tree by swapping the rows and columns. Note how the numbering is flipped so the columns climb in value (where previously the rows climbed in value):

Data Matching

This section discusses what data matching is and why it is important to understand.

Components in Grasshopper automatically handle wired-in single values, lists, as well as trees.

  • A component will process a single value once. 
  • A component will automatically loop or iterate over a list and process each element in the list. 
  • A component will automatically loop over a tree, dealing with each branch independently, and process each value or element in the list in the leaves of each branch. 
But what happens when a component is required to process both a list of values and a single value? Or a list and a tree? Whenever a situation like that arises, data matching is involved. This term refers to how the single value and the list of values are matched up and processed. Or how a list of values and trees of values are matched up and processed. Some simple examples will make this clear. You'll be introduce to the Grasshopper components which give you precise control over the processing.

Data Matching Lists of Points

The first few examples shows two lists of points. These points are fed into a Line component which takes two endpoint inputs and draws a line between them. One list is shorter (has less data) than the other.

A series component generates a list of values which become points with different Y coordinates. A second series generates another list of Y values, however these points are shifted one unit in X. These two lists are wired into the Line component which draws the line between them. This allows you to easily visualize the various types of matching between the two lists. Here's the simple definition:

Here's the result in the viewport - lines are drawn between points in the two lists:

As you can see, one list is shorter than the other. When Grasshopper does data matching to match up the values between the two lists, its default behavior is "longest list, repeat last". That means it uses the longest list for drawing the lines, thus there are 10 of them. It repeats the last item of the shorter list when it matches to the items in the longer list. This is the default behavior of Grasshopper.

There are two basic components which let you control data matching. Shortest List and Longest List. We'll look at Longest List first. The definition below is the same as the one above with the addition of a single Longest List component. As we saw above, longest list will repeat to the length of the longest list wired in. It has a right-click menu which let's you control how the repetition happens:

Longest List - Repeat First
You can see how the first item in the short list is repeated until there are enough items left to match up with the longer list.

Longest List - Repeat Last
This is the default case. You can see how the short list items are matched up with the longer list until they run out then the last item is repeated to match up with the remaining longest list.

Longest List - Interpolate
The items in the short list are uniformly distrubuted to the longer list. This results in four items being reused twice.

Longest List - Wrap
Here, after the shortest list items are used up they wrap back to beginning of that list and the matching happens from the beginning again.

Longest List - Flip
In this case, after the shortest list items are matched up, the longest list items starting matching back down, 7 to 5, 8 to 4, 9 to 3, and 10 to 2.

There's also a Shortest List component. In this case only the number of elements in the shortest list are matched up with those in the longer list. Right-click menu options let you choose between Trim End, Trim Start, and Interpolate. Here's the simple definition which demonstrates this:

Shortest List - Trim End
In this case the items at the end of the longest list are trimmed (not matched).

Shortest List - Trim Start
In this case, the items at the start of the longest list are trimmed (not matched).

Shortest List - Interpolate
In this case the items in the shortest list are distributed across the items in the longest list. As you can see this leaves four gaps in the matching but spans from the start to the end of the longest list.

Data Matching between a Tree and List

The next example shows data matching between a tree and a list. The tree is generated by the Rectangular grid component. The list is generated by a Series component. These are wired into a Longest List component which is set to Warp. 

You can see the results below. As we've seen previously each branch is treated independently. The series of 4 radius values are wired into the Circle component. The radius values wrap, that is they turn back to the smallest value once the list is fully used. So they get bigger for the 4 values in the series, then start over small. This happens independently in each branch. 

Compare this to when the tree is flattened (converted to a list). Take Note: these type of conversions are very commonly used and so there are right-click menus on the sockets of nodes to flatten, graft, etc. without having to wire in a component each time. That's what's done below: 

Here's the result - the values continue wrapping across all the (former) branches. Once the first column is done the radius values continue at the bottom of the next column. 

What happens if we Graft the list - turning it into a tree - how would this affect the data matching? This is done below: 

Now the matching is occurring between four branches of the radius data and four branches of the grid point data. Each branch is matched up one for one, so the first branch gets a branch with the smallest value. The next branch with the next biggest value, and so on. 


By understanding how Grasshopper matches data, and knowing the components which give you control over that matching, you can more quickly and successfully develop your definitions. This topic has presented the basics of dealing with single values, lists and trees and managing the flow of data between components.