Categories: Blog

Object color change using ARKit – iOS

What is Augmented Reality?

  1. Augmented reality is made up of the word “augment” which means to make something great by adding something to it.
  2. Augmented reality is used to add 2D or 3D objects to the live view using the device’s camera.
  3. Generally, Augmented Reality is used into indoor such as indoor path mapping, interior designing, airport, hospitals path mapping, games
  4. There are some popular applications which are using AR: LensKart, Pokemon GO, Real Strike and many more.
  5. You can also create many kinds of AR applications using the front or rear camera of the device.
  6. iPhone 6s and up devices with A9 chip and up devices support ARKit functionality. Please note, ARKit is not available to xCode Simulator.

What is ARNode?

  1. AR Node is used to add any objects on live view. It basically works on x-axis, y-axis and z-axis.
  2. We need to set all three axes for any object. Also, we can add multiple child objects for parent objects.
  3. For example, You’re creating a car game then we can add tyres, seats as a child of the parent node.
  4. For implementing AR into iOS. We need to import the ARKit package into the project.

In today’s demo, we are going to scan images and place objects on the screen. After that, we will fill colours on objects parts.

Let’s get started.

Step 1

Open Xcode -> Create New project -> Select options as mentioned in below image.

Step 2

Open Main. storyboard file, add sceneKit view, button, label to the ViewController and add constraints to it.

Step 3

Open ViewController.swift file and import below 2 libraries which are provided by apple default. After that, connect the scenekit with the outlet. Set delegate of sceneView inside viewDidLoad().
import ARKit
import SceneKit

@IBOutlet weak var sceneView: ARSCNView!

Step 4

Download object file from below mentioned link and add into app after that convert it to .scn file as mentioned below:

Step 5

Open Assets.xcassets -> Click on + from the bottom left corner as shown in below image. Add Robot image into AR Resources group and name it to Robot (It is case-sensitive).

Step 6

Create fade duration related variables.

let fadeDuration: TimeInterval = 0.3
let rotateDuration: TimeInterval = 5
let waitDuration: TimeInterval = 0.5

//MARK: create fade and spin action variable
lazy var fadeAndSpinAction: SCNAction = {
return .sequence([
.fadeIn(duration: fadeDuration),
.rotateBy(x: 0, y: 0, z: CGFloat.pi * 360 / 180, duration: rotateDuration),
.wait(duration: waitDuration),
])
}()

//MARK: create fade action variable
lazy var fadeAction: SCNAction = {
return .sequence([
.fadeOpacity(by: 0.8, duration: fadeDuration),
.wait(duration: waitDuration),
.fadeOut(duration: fadeDuration)
])
}()

//MARK: create SCNNode node type as robot node
lazy var robotNode: SCNNode = {
//create scene and replace robot.scn with your .scn filename
guard let scene = SCNScene(named: "robot.scn"),
//Add all child nodes of robot node
let node = scene.rootNode.childNode(withName: "robot", recursively: false) else { return SCNNode() }
let scaleFactor = 0.024

//all nodes added into this array
var nodeArray = scene.rootNode.childNodes
for childNode in nodeArray {
node.addChildNode(childNode as SCNNode)
}

node.scale = SCNVector3(scaleFactor, scaleFactor, scaleFactor)
node.pivot = SCNMatrix4MakeTranslation(0, 0, 0)
node.eulerAngles.x += -.pi / 2

//1. Get The Bounding Box Of The Node
let minimum = float3(node.boundingBox.min)
let maximum = float3(node.boundingBox.max)

//2. Set The Translation To Be Half Way Between The Vector
let translation = (maximum - minimum) * 0.5

//3. Set The Pivot
node.pivot = SCNMatrix4MakeTranslation(translation.x, translation.y, translation.z)

return node
}()

Step 7

Add tap gesture on scene view and call if from viewDidLoad().
//MARK: add tap gesture on the scene view

func registerGestureRecognizer() {
let tap = UITapGestureRecognizer(target: self, action: #selector(didTapped))
self.sceneView.addGestureRecognizer(tap)
}

Step 8

Configure lighting for scenview at the load time.

func configureLighting() {
sceneView.autoenablesDefaultLighting = true
sceneView.automaticallyUpdatesLighting = true
}

Step 9

Replace your viewDidLoad() function with below.

override func viewDidLoad() {
super.viewDidLoad()
sceneView.delegate = self
configureLighting()
registerGestureRecognizer()
}

Step 10

Add ARSCNViewDelegate to ViewController class.

extension ViewController: ARSCNViewDelegate {
//It renders image using camera ad gives name of the image
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
DispatchQueue.main.async {
guard let imageAnchor = anchor as? ARImageAnchor,
let imageName = imageAnchor.referenceImage.name else { return }
// TODO: Overlay 3D Object
let overlayNode = self.getNode(withImageName: imageName)
overlayNode.opacity = 0
overlayNode.position.y = 0.2
overlayNode.geometry?.firstMaterial!.diffuse.contents = nil
let moveLoop = SCNAction.repeatForever(self.fadeAndSpinAction)
overlayNode.runAction(moveLoop)
node.addChildNode(overlayNode)

self.label.text = "Image detected: \"\(imageName)\""
}
}

func getPlaneNode(withReferenceImage image: ARReferenceImage) -> SCNNode {
let plane = SCNPlane(width: image.physicalSize.width,
height: image.physicalSize.height)
let node = SCNNode(geometry: plane)
return node
}

func getNode(withImageName name: String) -> SCNNode {
var node = SCNNode()
switch name {
case "Robot":
node = robotNode
default:
break
}
return node
}
}

Step 11

create UIColor extension to generate random colors and assign it to tapped nodes.
extension UIColor {
/**
* Example:
* self.backgroundColor = UIColor.random
*/
static var random: UIColor {
let r:CGFloat = .random(in: 0…1)
let g:CGFloat = .random(in: 0…1)
let b:CGFloat = .random(in: 0…1)
return UIColor(red: r, green: g, blue: b, alpha: 1)
}
}

Step 12

Get node name of tapped and fill color on that particular node

@objc func didTapped(sender: UITapGestureRecognizer) {

let location = sender.location(in: sceneView)
let results = sceneView.hitTest(location, options: [SCNHitTestOption.searchMode : 1])
print("Touched node name : \(results.first?.node.name)")

results.first?.node.geometry?.firstMaterial?.diffuse.contents = UIColor.random
results.first?.node.geometry?.firstMaterial?.specular.contents = UIColor.white
}

For more details regarding Object color change using ARKit, contact us.

Lets Nurture

Share
Published by
Lets Nurture

Recent Posts

7 Powerful Psychological Triggers to Skyrocket Your Website Engagement

In the digital age, understanding the hidden forces driving user behavior is essential. By strategically…

7 months ago

What is haptics? How can we implement in in AR based mobile App? What are Haptics Use cases?

What is haptics?   Haptics refers to the use of touch feedback technology to simulate…

9 months ago

The Benefits of Using Virtual Reality in Business

In today's fast-paced and technologically driven world, businesses are constantly seeking innovative ways to stay…

1 year ago

A Closer Look at New Jersey’s Thriving Incubator Ecosystem

The Garden State, more popularly known as New Jersey, is not only known for its…

1 year ago

Why You Need a Mobile App for Your Business

In today's digital age, mobile apps have become an indispensable tool for businesses across all…

1 year ago

How to Optimize Your Website for Better User Experience

In today's digital era, a seamless and enjoyable user experience is crucial for the success…

1 year ago