Multiple Primitives


This isn’t exactly in the tutorial, but I am trying to place a bunch of spheres/planets in the view. Since they are just basic primitives, I am trying to implement them similarly to how just the one sphere was added in the early chapters, instead of importing a sphere as a .obj. I am trying to add them by adding the meshes to an array and then looping through the array, however, they don’t appear in the view. If possible, could you help me with how to go about doing this? Below are snippets of the main files, as well as the Node class.

import MetalKit

class Node {
var name: String = “untitled”
var position: float3 = [0, 0, 0]
var rotation: float3 = [0, 0, 0]
var scale: float3 = [1, 1, 1]

var modelMatrix: float4x4 {
    let translateMatrix = float4x4(translation: position)
    let rotateMatrix = float4x4(rotation: rotation)
    let scaleMatrix = float4x4(scaling: scale)
    return translateMatrix * rotateMatrix * scaleMatrix

var parent: Node?
var children: [Node] = []

final func add(childNode: Node) {
    childNode.parent = self

final func remove(childNode: Node) {
    // removes parent-child relationship between childNode and its own children, the parent node (or grandparent node) becomes a parent node to child node's children
    for child in childNode.children {
        child.parent = self
    // empties children array of child
    childNode.children = []
    // finds index of children where item is childNode and removes it
    guard let index = (children.firstIndex { $0 === childNode}) else { return }
    children.remove(at: index)
    childNode.parent = nil


Hi - would you be able to upload the complete project, please? It’s really difficult to see what’s going on when I don’t have the complete picture!

There could be all sorts of things happening with shaders and vertex descriptors etc.

It seems that I cannot upload the file because I am a new user. Here is the link to the project on Google Drive. Thank you, Caroline!

Thanks :slight_smile:

Your model matrix scale is out of this world :smiley: - try replacing the planet model matrix with identity, and work from there.

uniforms.modelMatrix = planet.modelMatrix    // from
uniforms.modelMatrix = float4x4.identity()   // to

Also, (1000, 1000) segments for the planet is pretty huge too. Do you need that kind of resolution? Until you get it working, I’d suggest putting it down to (10, 10).

There’s still something off about the mesh, but that gives you a starting position

In createPlanet, geometryType should be .triangles.

Screen Shot 2020-05-08 at 11.03.58 pm

Solar (193.9 KB)

Thank you so much, Caroline! My scale factors were too small by 3 orders of magnitude, which explains why I could not see them on the screen :grimacing:
Note to self, use print() often to debug :sweat_smile:

1 Like

Hello, Caroline, I hope I can bug you with another question (no pun intended… well, maybe).
I am trying to apply textures to my sun and planets now. Interestingly, when I add the UV attribute to the vertex descriptor, I get the following result when I run the program.

Screen Shot 2020-05-13 at 12.33.24

I am basically following the steps in Chapter 6: Textures for creating the UVs. Do you know why it is behaving this way? Is it because Metal does not unwrap the model, unlike Blender, and is unable to include a UV map for the descriptor to reference?

Here is the link to the project, if it will be easier for you to see.

If you change the drawIndexedPrimitives type to .point, you can see that the vertex positions have gone from vertical to spiral, and on the inside something wonky is happening.

Your pipeline state vertex descriptor does not match the mesh’s vertex descriptor.

This is the mesh’s vertex descriptor:

Screen Shot 2020-05-14 at 9.38.21 am

This is the pipeline’s vertex descriptor (using that default vertex descriptor extension method):

Screen Shot 2020-05-14 at 9.38.13 am

Print using this code:

for attribute in vertexDescriptor.attributes {
  let attribute = attribute as! MDLVertexAttribute

The chapters are using a default vertex descriptor with specific offsets to read from obj files. MDLMesh.sphereWithExtent uses different offsets. You can see that the mesh normal offset is 12, whereas the default one is 16.

I suspect that the book should be using 12, but the book instructs the obj file loader to use the default vertex descriptor, so the mesh buffer layout will use 16 with no problem. There will just be 4 byte gaps in the mesh buffer. You just have to make sure that the mesh vertex descriptor and the pipeline state vertex descriptor use the same format.

Change your default vertex descriptor to say:

offset += 12

in two places, and the planet will be round, and hopefully your uvs will fix themselves too.

Screen Shot 2020-05-14 at 10.16.39 am

Thank you for all your help, Caroline! I want to share the results with you :grin:

1 Like

That’s great :clap:!

Thank you so much for sharing :blush:

wow that is really cool