Post

Replies

Boosts

Views

Activity

Reply to SCNGeometry and .copy()
To create a unique instance, you need to do a "deep clone" or otherwise use recursion to instance everything as you see fit. extension SCNGeometry{ func deepClone() -> SCNGeometry? { // Use NSKeyedArchiver and NSKeyedUnarchiver to clone the geometry do { // Archive the geometry to Data let archivedData = try NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: true) // Unarchive the geometry from Data, specifying the expected class to ensure type safety let clonedGeometry = try NSKeyedUnarchiver.unarchivedObject(ofClass: SCNGeometry.self, from: archivedData) return clonedGeometry } catch { print("Error cloning geometry: \(error)") return nil } } } So you can change the material without changing the original. Each of these will take up more memory. You want to just copy them when possible.
4d
Reply to SCNNode from MDLMesh not rendered
Yes, that wasn't the issue. It doesn't like the order and there is overlap. It's easier to see when you reduce the nProfiles and print the arrays to visually inspect them. I don't even remember why I started using .makeVerticesUniqueAndReturnError() but it's not even needed here. let controlPoints: [(x: Float, y: Float)] = [ (0.728,-0.237), (0.176,-0.06), (0.202,0.475), (0.989,0.842), (-0.066,1.093), (-0.726,0.787) ] let pairs = bsplinePath(controlPoints) var knobProfile = [SCNVector3]() for (x,y) in pairs { knobProfile += [ SCNVector3(x: Float(x), y: Float(y), z: 0)] } let nProfiles = 20 let aIncrement: CGFloat = 2 * CGFloat.pi / CGFloat(nProfiles) var knobVertices: [SCNVector3] = [] for i in 0..<nProfiles { let angle = aIncrement * CGFloat(i) let rotatedProfile = knobProfile.map { $0.rotate(about: .y, by: Float(angle)) } knobVertices.append(contentsOf: rotatedProfile) } let source = SCNGeometrySource(vertices: knobVertices) var indices = [UInt16]() let profileCount = knobProfile.count for i in 0..<nProfiles { let nextProfileIndex = (i + 1) % nProfiles for j in 0..<profileCount - 1 { let currentIndex = UInt16(i * profileCount + j) let nextIndex = UInt16(nextProfileIndex * profileCount + j) let nextIndexNext = UInt16(nextProfileIndex * profileCount + j + 1) let currentIndexNext = UInt16(i * profileCount + j + 1) indices.append(contentsOf: [currentIndex, nextIndex, currentIndexNext]) indices.append(contentsOf: [currentIndexNext, nextIndex, nextIndexNext]) } } let element = SCNGeometryElement(indices: indices, primitiveType: .triangles) let surfaceGeometry = SCNGeometry(sources: [source], elements: [element]) let modelMesh = MDLMesh(scnGeometry: surfaceGeometry) let aluminum = SCNMaterial() aluminum.lightingModel = .physicallyBased aluminum.diffuse.contents = UIColor.green aluminum.roughness.contents = 0.2 aluminum.metalness.contents = 0.9 aluminum.isDoubleSided = true surfaceGeometry.materials = [aluminum] //let knobNode = SCNNode(geometry: surfaceGeometry) //return knobNode do{ try modelMesh.makeVerticesUniqueAndReturnError() modelMesh.addNormals(withAttributeNamed: "normal", creaseThreshold: 0.1) let flattenedGeom = SCNGeometry(mdlMesh: modelMesh) let flattenedNode = SCNNode(geometry: flattenedGeom) flattenedNode.geometry?.materials = [aluminum] return flattenedNode }catch{ fatalError("mesh vert error") } }
Nov ’24
Reply to SCNNode from MDLMesh not rendered
It's been awhile since I worked with this. I ultimately switched to calculating the normals for more control. Not that I'm a wiz with that stuff. A lot of hacking away. But the vertices need to be referred to uniquely for each face and there is a method for that. do{ try modelMesh.makeVerticesUniqueAndReturnError() modelMesh.addNormals(withAttributeNamed: "normal", creaseThreshold: 0.9) let flattenedGeom = SCNGeometry(mdlMesh: modelMesh) let flattenedNode = SCNNode(geometry: flattenedGeom) flattenedNode.geometry?.materials = [greenMaterial] return flattenedNode }catch{ print("mesh vert error") return node } I didn't try your code as it doesn't include bsplinePath.
Nov ’24
Reply to SKAction.removeFromParent() causes crash when run in SCNView.overlaySKScene on iOS
Yes, it does crash on the iPad simulator. It didn't crash for me on the iPhone simulator. Try this: let node = SKShapeNode(rect: CGRect(x: 100, y: 100, width: 100, height: 100)) node.fillColor = .yellow let removeAction = SKAction.run { DispatchQueue.main.async { node.removeFromParent() } } node.run(.sequence([ .fadeOut(withDuration: 5), removeAction])) renderer.overlaySKScene!.addChild(node)
Oct ’24
Reply to How to add a sort of engraving type of text to a mesh in SceneKit?
I tried to reply to the comment but character limit. I think "add normals" just literally adds the data for the normal vectors and puts them all at uniform value. It's just iterating through the vertices. You can sharpen or soften a custom mesh with it if you didn't want to create a SCNGeometrySource for normals. I wouldn't say programmatic normal maps are all that easy of a solution. It's just easier than writing your own boolean geometry routines. Have you tried to apply the image to the model? I imagine the image will be shrunken at the top and bottom and ballooned out at the equator. The best way to visualize this may still be to use Blender and create a mockup. See what the resulting maps look like for the look you want. Then that is what you would need to shoot for programmatically. I'm sure there are algorithms for this that can be adapted to Swift without reinventing the wheel.
Aug ’24
Reply to How to add a sort of engraving type of text to a mesh in SceneKit?
Boolean mesh functions are a little involved and not part of the frameworks last I checked. Not unless you get into voxels. You might look into applying this as a map instead. Normal maps can give the appearance of depth. It's easier to do this in 3D modeling software such as Blender and import the results. You'll need to understand the relationship of the UV map to the 3D vertices to do this programmatically.
Jul ’24
Reply to Apple Search Ads language glitch and odd replies
I just canceled the attempt to use Basic. The anonymous TechSupportGPT style replies were less than impressive and took 10 days to make any progress. The max spending was exceeding FB ads and still not spending. They also say one country isn't localized yet it's the exact same process used in all other localizations and they seem hung up on the fact that it uses the screen shots from the default localization. Which they admit is supposed to work that way. And all the other localizations use this without error. No indication in Connect that I need to do anything special for one localization. Just Basic ad's TechSupportGPT copypasta repeating it while seemingly failing to comprehend the questions. And I don't know if I'm talking to an LLM in those emails although they don't deny it. It's either an early version or a bad impression of one. But Apple needs to upgrade whichever they are using.
Jul ’24
Reply to SCNNode Pivot and Position
You should set the position as well. So you have your bounding box: var min = SCNVector3Zero var max = SCNVector3Zero node.__getBoundingBoxMin(&min, max: &max) The pivot at center: let pivot = SCNMatrix4MakeTranslation( min.x + (max.x - min.x)/2, min.y + (max.y - min.y)/2, min.z + (max.z - min.z)/2 ) This pivot is at x: m41, y: m42, z: m43 let posShift = SCNVector3( pivot.m41, pivot.m42, pivot.m43 ) so node.pivot = pivot node.position = posShift
Jul ’24