Reputation: 1091
I'm investigating iOS and trying to understand is it possible to change the texture of the model using any other picture?
Let's say I have model.obj with related texture green.png which is applied to this model so the appearance of the product is green. Is it possible to choose any other image, for example, blue.png, and apply it programmatically in runtime to 3d model and make the appearance of the product blue?
I have one working example
override func viewDidLoad() {
super.viewDidLoad()
let node = SCNNode()
let geometry = SCNSphere(radius: 0.2)
node.position = SCNVector3(0, 0, -1)
sceneView.backgroundColor = .black
sceneView.scene = SCNScene()
node.geometry = self.geometry
let image = UIImage(named: "art.scnassets/green.jpeg")
print(image)
node.geometry?.firstMaterial?.diffuse.contents = image
sceneView.scene.rootNode.addChildNode(node)
}
But when I try apply image to uploaded 3d model it's appearance doesn't change, here is a code.
override func viewDidLoad() {
super.viewDidLoad()
let tempScene = SCNScene(named: "art.scnassets/California_chair_1.obj")!
let node = tempScene.rootNode
node.position = SCNVector3(0, 0, -1)
sceneView.scene = SCNScene()
let image = UIImage(named: "art.scnassets/green.jpeg")
print(image)
/**/
let material = SCNMaterial()
material.isDoubleSided = false
material.diffuse.contents = image
node.geometry?.materials = [material]
/**/
node.geometry?.firstMaterial?.diffuse.contents = image
sceneView.scene.rootNode.addChildNode(node)
}
How to apply image to any 3d model created by designer?
Many thanks for any help!
Upvotes: 3
Views: 1405
Reputation: 58043
For retrieving a model from SCNScene, you may use subscript .childNodes[0]
several times to get to geometry and its corresponding materials in hierarchy.
import ARKit
class ViewController: UIViewController {
@IBOutlet var sceneView: ARSCNView!
let node = SCNNode()
override func viewDidLoad() {
super.viewDidLoad()
sceneView.scene = SCNScene(named: "art.scnassets/California_chair.scn")!
sceneView.autoenablesDefaultLighting = true
node = sceneView.scene.rootNode.childNode(withName: "firstChair",
recursively: true)
let green = UIColor.green
node?.childNodes[0].geometry?.firstMaterial?.diffuse.contents = green
}
@IBAction func changeTexture(_ sender: UIButton) {
let blue = UIImage(named: "art.scnassets/blueTexture.png")
node.geometry?.firstMaterial?.diffuse.contents = blue
}
}
Consider that SCNGeometry may be nested inside deep hierarchy:
node?.childNodes[0].childNodes[0].childNodes[0].geometry.firstMaterial?.diffuse
In Xcode's Scene graph
such a nested hierarchy looks like this:
Also always check your node's size (scale), to find out if your camera is inside 3D model or not.
P.S.
In case you use obj
models – use their corresponding mtl
textures:
sceneView.scene = SCNScene(named: "art.scnassets/file.obj")!
let obj = sceneView.scene.rootNode.childNode(withName: "default",
recursively: true)
obj?.geometry?.firstMaterial?.diffuse.contents = UIImage(named:
"art.scnassets/file.mtl")
Upvotes: 2