ios - 如何在 AR Kit 中将 UIImage 添加到场景中
问题描述
我有 AR 会话,它也添加了 SCNText 和 3D 对象。现在,我想从 Image Picker 添加 UIImage 并且不知道该怎么做。有什么解决办法吗?
解决方案
func insertImage(image: UIImage, width: CGFloat = 0.3, height: CGFloat = 0.3) -> SCNNode {
let plane = SCNPlane(width: width, height: height)
plane.firstMaterial!.diffuse.contents = image
let node = SCNNode(geometry: plane)
node.constraints = [SCNBillboardConstraint()]
return node
}
let image = insertImage(image: addedImage)
node.addChildNode(image)
解决方案
我相信您知道 anSCNGeometry
有一个materials
简单的属性:
一种材料视觉属性的颜色或纹理的容器。
因此,您可以使用例如diffuse 属性将a 渲染UIImage
到a 上。SCNGeometry
这是一个完整的工作和测试的例子。在 5 秒后加载一个UIImagePickerController
,然后创建一个SCNNode
其SCNPlane Geometry
内容设置为 selected 的内容UIImage
。
该代码已完全注释,因此应该很容易理解:
//-------------------------------------
//MARK: UIImagePickerControllerDelegate
//-------------------------------------
extension ViewController: UIImagePickerControllerDelegate{
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
//1. Check We Have A Valid Image
if let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
//2. We Havent Created Our PlaneNode So Create It
if planeNode == nil{
//d. Dismiss The Picker
picker.dismiss(animated: true) {
//a. Create An SCNPlane Geometry
let planeGeometry = SCNPlane(width: 0.5, height: 0.5)
//b. Set's It's Contents To The Picked Image
planeGeometry.firstMaterial?.diffuse.contents = self.correctlyOrientated(selectedImage)
//c. Set The Geometry & Add It To The Scene
self.planeNode = SCNNode()
self.planeNode?.geometry = planeGeometry
self.augmentedRealityView.scene.rootNode.addChildNode(self.planeNode!)
self.planeNode?.position = SCNVector3(0, 0, -1.5)
}
}
}
picker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { picker.dismiss(animated: true, completion: nil) }
}
class ViewController: UIViewController, UINavigationControllerDelegate {
//1. Create A Reference To Our ARSCNView In Our Storyboard Which Displays The Camera Feed
@IBOutlet weak var augmentedRealityView: ARSCNView!
//2. Create Our ARWorld Tracking Configuration & Session
let configuration = ARWorldTrackingConfiguration()
let augmentedRealitySession = ARSession()
//3. Create A Reference To Our PlaneNode
var planeNode: SCNNode?
var planeGeomeryImage: UIImage?
//---------------
//MARK: LifeCycle
//---------------
override func viewDidLoad() {
super.viewDidLoad()
//1. Setup The Session
setupARSession()
//2. Show The UIImagePicker After 4 Seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
self.selectPhotoFromGallery()
}
}
override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }
//-------------
//MARK: ARSetup
//-------------
func setupARSession(){
//1. Run Our Session
augmentedRealityView.session = augmentedRealitySession
augmentedRealitySession.run(configuration, options: [.resetTracking, .removeExistingAnchors])
}
//---------------------
//MARK: Image Selection
//---------------------
/// Loads The UIImagePicker & Allows Us To Select An Image
func selectPhotoFromGallery(){
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = true
imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
self.present(imagePicker, animated: true, completion: nil)
}
}
/// Correctly Orientates A UIImage
///
/// - Parameter image: UIImage
/// - Returns: UIImage?
func correctlyOrientated(_ image: UIImage) -> UIImage {
if (image.imageOrientation == .up) { return image }
UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
let rect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
image.draw(in: rect)
let normalizedImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return normalizedImage
}
}
不要忘记添加NSPhotoLibraryUsageDescription
到您的info.plist
:
<key>NSPhotoLibraryUsageDescription</key>
<string>For ARkit</string>
这应该足以让你开始......
推荐阅读
- python-3.x - NameError:在封闭范围内分配之前引用了自由变量“addcontact”
- python - 如何为熊猫数据帧的每一列应用具有不同时间常数的一阶过滤器?
- javascript - DOM 操作 - 按下按钮后添加 3 个新 div(可能使用 Node.cloneNode?)
- ios - 在 Swift 中添加阴影
- javascript - 使用解构赋值将对象作为函数的参数传递
- javascript - 执行查询直到将项目推送到数组 - React Query?
- typescript - 用于高阶函数泛型类型的 TypeScript 默认函数
- typescript - 如何像 apollo-client 一样在全球范围内处理联合类型?打字稿抛出属性'urls'在graphql Union的'Media'类型上不存在
- regex - Get digits after character in Google Sheets
- yaml - 如何在 .ebextensions 中测试是否未安装软件包?