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) {
children.append(childNode)
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
children.append(child)
}
// 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
}
Your model matrix scale is out of this world - 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
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
Note to self, use print() often to debug
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.
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?
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:
This is the pipeline’s vertex descriptor (using that default vertex descriptor extension method):
Print using this code:
for attribute in vertexDescriptor.attributes {
let attribute = attribute as! MDLVertexAttribute
print(attribute)
}
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.