Home iOS & Swift Books Metal by Tutorials

5
3D Transformations Written by Marius Horga & Caroline Begbie

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

You can unlock the rest of this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

In the previous chapter, you translated vertices and moved objects around the screen by calculating the position data in the vertex function. But there’s a lot more you’ll want to do when working in 3D space, such as rotating and scaling your objects. You’ll also want to have an in-scene camera so that you can move around your scene.

To move, scale and rotate a triangle, you’ll use matrices — and once you’ve mastered one triangle, it’s a cinch to rotate a model with thousands of triangles at once!

For those of us who aren’t math geniuses, vectors and matrices can be a bit scary. Fortunately, you don’t always have to know what’s under the hood when using math. To help, this chapter focuses not on the math, but the matrices. As you work through this chapter, you’ll gradually extend your linear algebra knowledge as you learn what matrices can do for you and how to manipulate them.

Transformations

Look at the following picture.

Affine Transformations
Affine Transformations

Using the vector image editor, Affinity Designer, you can scale and rotate a cat through a series of affine transformations. Instead of individually calculating each position, Affinity Designer creates a transformation matrix that holds the combination of the transformations. It then applies the transformation to each element.

Note: Affine means that after you’ve done the transformation, all parallel lines remain parallel.

Of course, no one wants to translate, scale and rotate a cat since they’ll probably bite. So instead, you’ll translate, scale and rotate a triangle.

The Starter Project & Setup

➤ Open and run the starter project located in the starter folder for this chapter.

The starter project
Gzu bmopfup rseloym

Setting Up the Preview Using SwiftUI

When making small tweaks, you can preview your changes using SwiftUI rather than running the project each time. You’ll pin the preview so that no matter what file you open, the preview remains visible.

Showing the preview canvas
Ssifesz ssa gtugion qaskec

The preview
Yto bkomuaw

Pinning the preview
Daxtusy tri cpoquum

Translation

The starter project renders two triangles:

Displacement Vectors
Bugqwezelayk Vufkosx

Vectors & Matrices

You can better describe position as a displacement vector of [0.3, -0.4, 0]. You move each vertex 0.3 units in the x-direction, and -0.4 in the y-direction from its starting position.

Vectors
Jewhuxc

An identity matrix
Af omelqegh sonyej

The Magic of Matrices

When you multiply matrices, you combine them into one matrix. You can then multiply a vector by this matrix to transform the vector. For example, you can set up a rotation matrix and a translation matrix. You can then calculate the transformed position with the following line of code:

translationMatrix * rotationMatrix * positionVector

Creating a Matrix

➤ Open Renderer.swift, and locate where you render the first gray triangle in draw(in:).

var position = simd_float3(0, 0, 0)
renderEncoder.setVertexBytes(
  &position,
  length: MemoryLayout<SIMD3<Float>>.stride,
  index: 11)
var translation = matrix_float4x4()
translation.columns.0 = [1, 0, 0, 0]
translation.columns.1 = [0, 1, 0, 0]
translation.columns.2 = [0, 0, 1, 0]
translation.columns.3 = [0, 0, 0, 1]
var matrix = translation
renderEncoder.setVertexBytes(
  &matrix,
  length: MemoryLayout<matrix_float4x4>.stride,
  index: 11)
position = simd_float3(0.3, -0.4, 0)
renderEncoder.setVertexBytes(
  &position,
  length: MemoryLayout<SIMD3<Float>>.stride,
  index: 11)
let position = simd_float3(0.3, -0.4, 0)
translation.columns.3.x = position.x
translation.columns.3.y = position.y
translation.columns.3.z = position.z
matrix = translation
renderEncoder.setVertexBytes(
  &matrix,
  length: MemoryLayout<matrix_float4x4>.stride,
  index: 11)
constant float3 &position [[buffer(11)]])
constant float4x4 &matrix [[buffer(11)]])
float3 translation = in.position.xyz + position;
float3 translation = in.position.xyz + matrix.columns[3].xyz;
Translation by adding a matrix column to the position
Kkicrzawaas hd edbuwc i fahjam nuqoyg ge ftu fixilaaw

float4 translation = matrix * in.position;
VertexOut out {
  .position = translation
};
return out;

Scaling

➤ Open Renderer.swift, and in draw(in:), locate where you set matrix in the second red triangle.

let scaleX: Float = 1.2
let scaleY: Float = 0.5
let scaleMatrix = float4x4(
  [scaleX, 0,   0,   0],
  [0, scaleY,   0,   0],
  [0,      0,   1,   0],
  [0,      0,   0,   1])
matrix = scaleMatrix
Scaling with a matrix
Cbuzexg vevm o yasfub

matrix = translation * scaleMatrix
A translated and scaled triangle
I ymowtyucic opz wtokat qjiukdhi

Rotation

You perform rotation in a similar way to scaling.

let angle = Float.pi / 2.0
let rotationMatrix = float4x4(
  [cos(angle), -sin(angle), 0,    0],
  [sin(angle),  cos(angle), 0,    0],
  [0,           0,          1,    0],
  [0,           0,          0,    1])

matrix = rotationMatrix
Rotating about the origin
Yubavihn ogiuf ywo oguced

matrix = translation * rotationMatrix * scaleMatrix
Scale, rotate and translate
Wvise, dunebo icc kweslfoja

translation.columns.3.x = triangle.vertices[6]
translation.columns.3.y = triangle.vertices[7]
translation.columns.3.z = triangle.vertices[8]
matrix = translation.inverse
Rotate about a point (1)
Cefipu ehaum u seuqs (2)

matrix = rotationMatrix * translation.inverse
Rotate about a point (2)
Pekupe inion i guebm (8)

matrix = translation * rotationMatrix * translation.inverse
Rotate about a point (3)
Jumagu ameos u duocl (5)

Key Points

  • A vector is a matrix with only one row or column.
  • By combining three matrices for translation, rotation and scale, you can position a model anywhere in the scene.
  • In the resources folder for this chapter, references.markdown suggests further reading to help better understand transformations with linear algebra.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.

© 2022 Razeware LLC

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

Unlock Now

To highlight or take notes, you’ll need to own this book in a subscription or purchased by itself.