/
Plane.swift
69 lines (54 loc) · 2.57 KB
/
Plane.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//
// Plane.swift
// ARCube
//
// Created by 张嘉夫 on 2017/7/10.
// Copyright © 2017年 张嘉夫. All rights reserved.
//
import UIKit
import SceneKit
import ARKit
class Plane: SCNNode {
var anchor: ARPlaneAnchor!
var planeGeometry: SCNPlane!
init(withAnchor anchor: ARPlaneAnchor) {
super.init()
self.anchor = anchor
planeGeometry = SCNPlane(width: CGFloat(anchor.extent.x), height: CGFloat(anchor.extent.z))
// 相比把网格视觉化为灰色平面,我更喜欢用科幻风的颜色来渲染
let material = SCNMaterial()
let img = UIImage(named: "fabric")
material.diffuse.contents = img
material.lightingModel = .physicallyBased
planeGeometry.materials = [material]
let planeNode = SCNNode(geometry: planeGeometry)
planeNode.position = SCNVector3Make(anchor.center.x, 0, anchor.center.z)
// SceneKit 里的平面默认是垂直的,所以需要旋转90度来匹配 ARKit 中的平面
planeNode.transform = SCNMatrix4MakeRotation(Float(-.pi / 2.0), 1.0, 0.0, 0.0)
setTextureScale()
addChildNode(planeNode)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func update(anchor: ARPlaneAnchor) {
// 随着用户移动,平面 plane 的 范围 extend 和 位置 location 可能会更新。
// 需要更新 3D 几何体来匹配 plane 的新参数。
planeGeometry.width = CGFloat(anchor.extent.x);
planeGeometry.height = CGFloat(anchor.extent.z);
// plane 刚创建时中心点 center 为 0,0,0,node transform 包含了变换参数。
// plane 更新后变换没变但 center 更新了,所以需要更新 3D 几何体的位置
position = SCNVector3Make(anchor.center.x, 0, anchor.center.z)
setTextureScale()
}
func setTextureScale() {
let width = planeGeometry.width
let height = planeGeometry.height
// 平面的宽度/高度 width/height 更新时,我希望 tron grid material 覆盖整个平面,不断重复纹理。
// 但如果网格小于 1 个单位,我不希望纹理挤在一起,所以这种情况下通过缩放更新纹理坐标并裁剪纹理
let material = planeGeometry.materials.first
material?.diffuse.contentsTransform = SCNMatrix4MakeScale(Float(width), Float(height), 1)
material?.diffuse.wrapS = .repeat
material?.diffuse.wrapT = .repeat
}
}