Zdog models are built with shapes. Shapes can be positioned with `translate`

. Their positions are *relative*. For instance, when added to an `Illustration`

, shapes are positioned relative to the `Illustration`

’s origin.

```
let zCircle = new Zdog.Ellipse({
addTo: illo,
translate: { z: 40 }, // z +40 from illo
// ...
});
let xRect = new Zdog.Rect({
addTo: illo,
translate: { x: 40 }, // x +40 from illo
// ...
});
let yTri = new Zdog.Polygon({
addTo: illo,
translate: { y: -60 }, // y -60 from illo
// ...
});
```

Shapes can be added as children to other shapes. A child shape is positioned relative to its parent.

```
let zCircle = new Zdog.Ellipse({
addTo: illo,
translate: { z: 40 }, // z +40 from illo
// ...
});
let xRect = new Zdog.Rect({
addTo: zCircle,
translate: { x: 40 }, // x +40 from zCircle
// ...
});
let yTri = new Zdog.Polygon({
addTo: xRect,
translate: { y: -60 }, // y -60 from xRect
// ...
});
```

`translate`

is a transform — as is `rotate`

and `scale`

. Child shapes inherit the transforms of their parents (*wow, that is deep*).

```
let zCircle = new Zdog.Ellipse({
addTo: illo,
scale: 1.5, // scale 150%
translate: { z: 40 },
rotate: { z: -Zdog.TAU/8 }, // rotate 45° CCW
// ...
});
let xRect = new Zdog.Rect({
addTo: zCircle,
translate: { x: 40 },
rotate: { x: Zdog.TAU/8 }, // rotate back
// ...
});
let yTri = new Zdog.Polygon({
addTo: xRect,
translate: { y: -60 },
// ...
});
```

Using child shapes and their additive transforms enables you to build complex models.

An `Anchor`

is an invisible shape. Use an `Anchor`

for transforms without rendering a shape.

```
let zAnchor = new Zdog.Anchor({
addTo: illo,
scale: 1.5,
translate: { z: 40 },
rotate: { z: -Zdog.TAU/8 },
});
let xAnchor = new Zdog.Anchor({
addTo: zAnchor,
translate: { x: 40 },
rotate: { x: Zdog.TAU/8 },
});
let yTri = new Zdog.Polygon({
addTo: xAnchor,
translate: { y: -60 },
// ...
});
```

Properties like `translate`

, `rotation`

, and `scale`

are `Vector`

s. A `Vector`

can be set with a vector *Object*.

A vector *Object* is a plain ol' JavaScript *Object* with `x`

, `y`

, `z`

coordinate properties. The coordinate properties are optional. They default to `0`

if undefined. So you only need to set non-zero values.

```
translate: { x: 1, z: 2 }, // => { x: 1, y: 0, z: 2 }
translate: { y: 3 }, // => { x: 0, y: 3, z: 0 }
translate: {} // => { x: 0, y: 0, z: 0 }
```

Copy items with `.copy()`

.

```
// create original
let rect = new Zdog.Rect({
addTo: illo,
width: 64,
height: 64,
translate: { x: -48 },
stroke: 16,
color: '#EA0',
});
// copy
rect.copy({
// overwrite original options
translate: { x: 48 },
color: '#C25',
});
```

Copy items with their children with `.copyGraph()`

.

```
// create original
let rect = new Zdog.Rect({
// ...
});
// add child item
new Zdog.Shape({
addTo: rect,
// ...
});
// copy rect and its children
rect.copyGraph({
// overwrite original rect options
translate: { x: 48 },
color: '#C25',
});
```

Whereas polygonal 3D engines rely on meshes of polygons to depict volume, Zdog shapes can show volume with `stroke`

.

Look at this tasty burger. The patty and cheese slice are just simple circles. The sesame seeds are just lines. But with thick `stroke`

they appear as plump round discs and pills.

```
// cheese
new Zdog.Rect({
width: 92,
height: 92,
stroke: 16,
// ...
});
// patty
new Zdog.Ellipse({
diameter: 72,
stroke: 28,
// ...
});
// seed
new Zdog.Shape({
path: [ { y: -3 }, { y: 3 } ],
stroke: 8,
// ...
});
```

**Using stroke for volume is what makes Zdog special.** Let go of your earthly polygons and become one with the round thickness.

Use a `Group`

to control rendering order. Shapes will be rendered in the order they are added to the `Group`

. `Group`

s are useful for positioning shapes within other shapes, like windows in walls or pupils in eyes.

```
// render shapes in order added
var eyeGroup = new Zdog.Group({
addTo: illo,
translate: { z: 20 },
});
// eye white first
new Zdog.Ellipse({
addTo: eyeGroup,
width: 160,
height: 80,
// ...
});
// then iris
let iris = new Zdog.Ellipse({
addTo: eyeGroup,
diameter: 70,
// ...
});
// then pupil
iris.copy({
diameter: 30,
color: '#636',
});
// highlight last in front
iris.copy({
diameter: 30,
translate: { x: 15, y: -15 },
color: 'white',
});
```

Modeling with Zdog is done by positioning and combining shapes to make more complex objects. This tutorial will walk through modeling this high-struttin' dude.

Our initial setup picks up from the Getting started demo. We have an `Illustration`

, a model with a single `Shape`

, and an animation loop.

```
let illo = new Zdog.Illustration({
element: elem,
zoom: 10,
dragRotate: true,
});
// ---- model ---- //
let head = new Zdog.Shape({
addTo: illo,
stroke: 12,
color: gold,
});
// -- animate --- //
function animate() {
illo.updateRenderGraph();
requestAnimationFrame( animate );
}
animate();
```

The head shape is rendered as a flat-colored sphere with `Shape`

. The `Shape`

class can be defined to render any shape — lines, curves, polygons — via its `path`

property. As `head`

does not have `path`

set, its path defaults to a single point. That point, with `stroke`

volume, renders a flat-colored sphere. In other words, a circle.

Next we add the eye `Ellipse`

as a child shape to `head`

with `addTo: head`

.

```
let eye = new Zdog.Ellipse({
addTo: head,
diameter: 2,
quarters: 2, // semi-circle
translate: { x: -2, y: 1, z: 4.5 },
// rotate semi-circle to point up
rotate: { z: -TAU/4 },
color: eggplant,
stroke: 0.5,
// hide when front-side is facing back
backface: false,
});
```

For the eye on the right, we can `.copy()`

the right. The original options are copied over and then can be overwritten with new options, in this case changing `translate`

.

```
// eye on left
let eye = new Zdog.Ellipse({
addTo: head,
diameter: 2,
quarters: 2,
translate: { x: -2, y: 1, z: 4.5 },
// ...
});
// eye on right
eye.copy({
translate: { x: 2, y: 1, z: 4.5 },
});
```

Compare the `translate`

vector *Object*s for the eyes.

```
// eye on left
translate: { x: -2, y: 1, z: 4.5 }
// eye on right
translate: { x: 2, y: 1, z: 4.5 }
```

The only difference is the `x`

coordinate. But all three `x`

, `y`

, `z`

coordinates need to be set. Setting just `translate: { x: 2 }`

would yield `{ x: 2, y: 0, z: 0 }`

which is not what we want.

The smile is made with a similar semi-circle `Ellipse`

. Its path is closed with `closed: true`

.

```
// smile
new Zdog.Ellipse({
addTo: head,
diameter: 3,
quarters: 2,
translate: { y: 2.5, z: 4.5 },
rotate: { z: TAU/4 },
closed: true,
color: '#FED',
stroke: 0.5,
fill: true,
backface: false,
});
```

Let’s give this floating head a body starting with the hips.

```
// illo zoom: 5
// remove head for now
let hips = new Zdog.Shape({
addTo: illo,
path: [ { x: -3 }, { x: 3 } ],
stroke: 4,
color: '#636',
});
```

`hips`

is just a horizontal line `Shape`

. Unlike `head`

, `hips`

has its `path`

set. The `path`

is set to an *Array* with two vector *Object*s. So this path reads: start at `x: -3`

, draw a line to `x: 3`

.

We start with the hips because the model’s upper body pivots around the hips. By adding the upper body shapes to hips, we can rotate the hips and shapes will rotate with it.

Let’s work our way up and add the chest next.

```
let chest = new Zdog.Shape({
addTo: hips,
path: [ { x: -1.5 }, { x: 1.5 } ],
// position right above hips
// ( hips.stroke + chest.stroke ) / 2
translate: { y: -6.5 },
stroke: 9,
color: '#C25',
});
```

`chest`

is another horizontal line `Shape`

. Ample stroke gives makes this little line a big barrelled torso.

The head can now go back on top.

```
let head = new Zdog.Shape({
addTo: chest,
stroke: 12,
// position above chest
translate: { y: -9.5 },
color: '#EA0',
});
// other face shapes...
```

Now we can rotate `illo`

and `hips`

to see a preview of the final product.

```
let illo = new Zdog.Illustration({
zoom: 5,
// rotate for three-quarters view
rotate: { y: -Zdog.TAU/8 },
// ...
});
let hips = new Zdog.Shape({
addTo: illo,
// tilt back 45°
rotate: { x: Zdog.TAU/8 },
// ...
});
```

So chill.

Let’s get back upright and now work on the lower half.

```
let hipX = 3;
let hips = new Zdog.Shape({
path: [ { x: -hipX }, { x: hipX } ],
// ...
});
let leg = new Zdog.Shape({
addTo: hips,
path: [ { y: 0 }, { y: 12 } ],
translate: { x: -hipX },
color: '#636',
stroke: 4,
});
```

We can render a leg with a straight line `Shape`

. This line will start at the left hip. So we add the `leg`

to `hips`

and set its origin with `translate: { x: -hipX }`

. We can use a variable `hipX`

within both `hips.path`

and `leg.translate`

for consistency. Now we can draw the `path`

starting at the origin `0`

and go down, hence `path: [ { y: 0 }, { y: 12 } ]`

.

Next, the foot.

```
// foot
new Zdog.RoundedRect({
addTo: leg,
width: 2,
height: 4,
cornerRadius: 1,
// y: past leg end, z: scootch toward front
translate: { y: 14, z: 2 },
color: '#C25',
fill: true,
stroke: 4,
});
```

The foot is first shape we need to consider in three dimensions. The toe sticks out toward the front. We could draw a custom `Shape`

that works with `z`

values. But instead, a simpler approach is to rotate a basic shape into the desired orientation.

This simple foot is rendered with a `RoundedRect`

. The corners are completely rounded with `cornerRadius: 1`

, forming a flattened pill shape. The foot is added to `leg`

and positioned vertically a little past the end of the leg, and along `z`

toward the front so the toe sticks out farther than the heel.

Now let’s rotate that foot.

```
// foot
new Zdog.RoundedRect({
addTo: leg,
translate: { y: 14, z: 2 },
// rotate 90° along x-axis
rotate: { x: Zdog.TAU/4 }
// ...
});
```

Perfecto. Now that one leg is in place, we can copy the leg and its foot with `.copyGraph()`

.

```
leg.copyGraph({
// position on right
translate: { x: hipX },
});
```

This fella needs some dukes for puttin' up. We'll use the same technique with the legs, this time working off the `chest`

.

```
var armSize = 6;
// left arm
let upperArm = new Zdog.Shape({
addTo: chest,
path: [ { y: 0 }, { y: armSize } ],
translate: { x: -5, y: -2 },
color: '#636',
stroke: 4,
});
```

Whereas the leg was just one straight line from hip to foot, the arm will require two parts. The first `upperArm`

shape starts from the `chest`

.

```
let forearm = new Zdog.Shape({
addTo: upperArm,
path: [ { y: 0 }, { y: armSize } ],
translate: { y: armSize },
color: '#EA0',
stroke: 4,
});
```

The `forearm`

connects to the `upperArm`

. It starts at the end of the `upperArm`

by setting `translate: { y: armSize }`

, which matches `upperArm`

’s end `path`

point.

```
// hand
new Zdog.Shape({
addTo: forearm,
// connect to end of forearm
// scootch toward front a bit
translate: { y: armSize, z: 1 },
stroke: 6,
color: '#EA0',
});
```

The hand is rendered as a single-point `Shape`

like the `head`

. It connects to `forearm`

.

```
// copy to right arm
upperArm.copyGraph({
translate: { x: 5, y: -2 },
});
```

Whoa! All the body parts are in place.

Rotating the model around, you'll notice how the shapes pop-over one another — like where the `upperArm`

and `forearm`

overlap on the elbow. This is called z-fighting. We'll clean this up a bit as we rotate shapes away from one another. But these z-fights are innevitable with pseudo-3D engine like Zdog. Rather than fighting this effect, accept it for what it is. It’s not a bug, it’s what makes Zdog *charming*.

Let’s kick it. First let’s adjust the position and rotation of the figure for better viewing.

```
const TAU = Zdog.TAU; // easier to read constant
let illo = new Zdog.Illustration({
// rotate for three-quarters view
rotate: { y: -TAU/8 },
// ...
});
let hips = new Zdog.Shape({
// move down a little
translate: { y: 2 },
// ...
});
```

The leg on the left needs to be rotated 90°. As a kick would be rotating the leg’s horizontal axis, that means rotating around the `x`

axis.

```
let leg = new Zdog.Shape({
addTo: hips,
path: [ { y: 0 }, { y: 12 } ],
translate: { x: -hipX },
// rotate leg
rotate: { x: TAU/4 },
color: eggplant,
stroke: 4,
});
```

I like to use `TAU`

in to set `rotate`

values. `TAU`

is a full rotation in radians, equal to `2 * Math.PI`

. So `TAU/4`

is a quarter-turn.

Items rotate around their origin. The `leg`

’s origin is its first point, which we set in its path, `[ { y: 0 }, { y: 12 } ]`

.

Both legs are rotated because the leg on the right copied the properties of the left. So let’s rotate the right leg to its position.

```
// leg on left
let leg = new Zdog.Shape({
translate: { x: -hipX },
rotate: { x: TAU/4 },
// ...
});
// foot
new Zdog.RoundedRect({
addTo: leg,
// ...
});
// leg on right
leg.copyGraph({
translate: { x: hipX },
rotate: { x: -TAU/8 },
});
```

The legs are in the place. But the bottom foot needs to look flat on the ground. Again, it’s copied over its rotate value from the other foot. So we need to overwrite it.

```
// kick foot
let foot = new Zdog.RoundedRect({
addTo: leg,
rotate: { x: TAU/4 },
// ...
});
// leg on right
let standLeg = leg.copy({
translate: { x: hipX },
rotate: { x: -TAU/8 },
});
// stand foot
foot.copy({
addTo: standLeg,
rotate: { x: -TAU/8 },
});
```

To separate the feet, we change `leg.copyGraph()`

to `leg.copy()`

. Now the kick `foot`

can be copied, added to `standLeg`

, and have its `rotate`

value set.

And a perfectly normal-looking gait is rendered. So realistic!

Let’s tilt the figure back upper body back by rotating the `hips`

.

```
let hips = new Zdog.Shape({
rotate: { x: TAU/8 },
// ...
});
```

Uh oh. By rotating `hips`

the entire figure was rotated — as all the shapes are descendents of `hips`

.

One way to resolve this is by adding a separate `Anchor`

to rotate just the upper body shapes.

```
// separate anchor just for rotating upper body
let spine = new Zdog.Anchor({
addTo: hips,
rotate: { x: TAU/8 },
});
let chest = new Zdog.Shape({
// add chest to spine instead of hips
addTo: spine,
// ...
});
```

Last step: arms.

The arms can be rotated just like the legs.

```
// arm on left
let upperArm = new Zdog.Shape({
translate: { x: -5, y: -2 },
// rotate back 90°
rotate: { x: -TAU/4 },
// ...
});
// forearm & hand...
// arm on right
upperArm.copyGraph({
translate: { x: 5, y: -2 },
// rotate forward 90°
rotate: { x: TAU/4 },
});
```

Both `forearm`

and hand shapes continue to stick straight away from the `upperArm`

. To bend the elbow, we can rotate `forearm`

.

```
let forearm = new Zdog.Shape({
addTo: upperArm,
rotate: { x: TAU/8 },
// ...
});
```

We only have to rotate the one forearm as the relative angle of rotation of the forearms compared to their parent upper-arm shapes is the same.

It’s done!

Now that the model is complete, try going back and make some changes. How would you rotate the arms for a T-pose? How could you break up the legs into thigh and shin like we did for the arms? What shapes could be used to show an angry face?

This tutorial covers the basic of shape composition with Zdog. Now you're ready to start making your own models. Take a look at API for all of Zdog’s functionality and Shapes for all the shapes.