0
votes

Im finding difficult to caste a shadow on invisible plane in scenekit , firstly I am trying to create an invisible plane under my AR Object and casting shadow on it , so far failed to do both

One thing Im doing right is that my object has the shadow on other AR object but not on ground (because I think Im unable to create the invisible plane on which shadow will be casted)

Note : Im using apple's demo project code for my project

Kindly Help , Thanks in advance

didAdd node delegate

    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    guard let planeAnchor = anchor as? ARPlaneAnchor else { return }

    DispatchQueue.main.async {
        self.statusViewController.cancelScheduledMessage(for: .planeEstimation)
        self.statusViewController.showMessage("SURFACE DETECTED")
        if self.virtualObjectLoader.loadedObjects.isEmpty {
            self.statusViewController.scheduleMessage("TAP ON SCREEN TO PLACE AN OBJECT", inSeconds: 7.5, messageType: .contentPlacement)
        }
    }
    updateQueue.async {
        for object in self.virtualObjectLoader.loadedObjects {
            object.adjustOntoPlaneAnchor(planeAnchor, using: node)
        }
    }
}

didUpdate node delegate

   func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
    guard let planeAnchor = anchor as? ARPlaneAnchor ,
          let planeNode = node.childNodes.first,let plane = planeNode.geometry as? SCNPlane else { return }
     
    // 2
    let width = CGFloat(planeAnchor.extent.x)
    let height = CGFloat(planeAnchor.extent.z)
    plane.width = width
    plane.height = height
     
    // 3
    let x = CGFloat(planeAnchor.center.x)
    let y = CGFloat(planeAnchor.center.y)
    let z = CGFloat(planeAnchor.center.z)
    planeNode.position = SCNVector3(x, y, z)
    updateQueue.async {
        for object in self.virtualObjectLoader.loadedObjects {
            object.adjustOntoPlaneAnchor(planeAnchor, using: node)
        }
    }
}

casting shadow on other object

enter image description here

1

1 Answers

1
votes

Try it like so:

The plane for the shadows:

func shadowPlane() -> SCNNode {

    let objectShape                    = SCNPlane(width: 30.0, height: 30.0)
    objectShape.heightSegmentCount     = 1
    objectShape.widthSegmentCount      = 1

    let objectNode                     = SCNNode(geometry: objectShape)
    objectNode.renderingOrder          = -10 // for Shadow Material Standard
    objectNode.position                = yourPosition
    objectNode.geometry?.firstMaterial = shadowMaterialStandard()
    objectNode.castsShadow             = false // Important
    objectNode.eulerAngles             = SCNVector3(CGFloat.pi/2, 0.0, 0.0)
    objectNode.name                    = "floor"

    return objectNode
}

For the Material:

func shadowMaterialStandard() -> SCNMaterial {
    
    let material                  = SCNMaterial()
    
    material.colorBufferWriteMask = SCNColorMask(rawValue: 0) // important
    material.diffuse.contents     = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
    material.lightingModel        = .physicallyBased // OK
    material.isDoubleSided        = true
    
    return material
}

For the Lighting:

func directionalLight() -> SCNLight {
    
    let light                           = SCNLight()
    light.type                          = .directional
    light.castsShadow                   = true
    light.color                         = UIColor.white
    light.shadowColor                   = UIColor(red: 0, green: 0, blue: 0, alpha: 0.75)
    light.shadowMode                    = .deferred
    light.shadowRadius                  = 2.0  // 3.25 // suggestion by StackOverflow
    light.shadowCascadeCount            = 3    // suggestion by StackOverflow
    light.shadowCascadeSplittingFactor  = 0.09 // suggestion by StackOverflow
    light.shadowBias                    = 0.1  // what's this?
    light.shadowSampleCount             = 8    // Quality of the Shadow - impacts performance when to high
    light.categoryBitMask               = -1   // Shine on Everything

    return light
}

func ambientLight() -> SCNLight {

    let light               = SCNLight()
    light.type              = .ambient
    light.color             = UIColor.white
    light.intensity         = 250
    light.categoryBitMask   = -1 // Shine on Everything

    return light
}