├── .gitignore
├── BoundingBoxOnScreen.playground
├── Contents.swift
├── contents.xcplayground
└── playground.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── README.md
└── screenshot.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 |
20 | # CocoaPods
21 | #
22 | # We recommend against adding the Pods directory to your .gitignore. However
23 | # you should judge for yourself, the pros and cons are mentioned at:
24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
25 | #
26 | Pods/
27 |
28 | # Carthage
29 | #
30 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
31 | # Carthage/Checkouts
32 |
33 | Carthage/Build
34 |
35 | # etc
36 | Framework/
37 | *~
38 | *.swp
39 |
40 |
--------------------------------------------------------------------------------
/BoundingBoxOnScreen.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | import PlaygroundSupport
2 | import AppKit
3 | import SpriteKit
4 | import SceneKit
5 |
6 | class BBView: SCNView, SCNSceneRendererDelegate {
7 | var trackingNode: SCNNode!
8 | var boundingBox: SKShapeNode!
9 | let bbSize: CGFloat = 20.0
10 | var sizeLabel: SKLabelNode!
11 |
12 | init() {
13 | super.init(frame: NSRect(x: 0, y: 0, width: 400, height: 250), options: nil)
14 |
15 | self.autoenablesDefaultLighting = true
16 | self.backgroundColor = SKColor.gray
17 | self.allowsCameraControl = true
18 |
19 | self.showsStatistics = true
20 | self.debugOptions = .showBoundingBoxes
21 |
22 | self.setupScene()
23 | self.setupSKScene()
24 |
25 | self.delegate = self
26 | }
27 |
28 | required init?(coder: NSCoder) {
29 | fatalError("init(coder:) has not been implemented")
30 | }
31 |
32 | func setupScene() {
33 | let scene = SCNScene()
34 | self.scene = scene
35 |
36 | // set camera node
37 | let cameraNode = SCNNode()
38 | let camera = SCNCamera()
39 | cameraNode.camera = camera
40 | scene.rootNode.addChildNode(cameraNode)
41 | self.pointOfView = cameraNode
42 |
43 | // create a sphere
44 | let sphere = SCNSphere(radius: 1.0)
45 | self.trackingNode = SCNNode(geometry: sphere)
46 | self.trackingNode.position = SCNVector3(0, 0, -10.0)
47 | scene.rootNode.addChildNode(self.trackingNode)
48 | }
49 |
50 | func setupSKScene() {
51 | let skScene = SKScene(size: self.bounds.size)
52 | self.overlaySKScene = skScene
53 |
54 | self.boundingBox = SKShapeNode(rect: CGRect(x: 0, y: 0, width: self.bbSize, height: self.bbSize))
55 | self.boundingBox.strokeColor = SKColor.red
56 | self.boundingBox.lineWidth = 3
57 |
58 | skScene.addChild(self.boundingBox)
59 |
60 | self.sizeLabel = SKLabelNode(fontNamed: "Arial")
61 | self.sizeLabel.fontSize = 24
62 | self.sizeLabel.fontColor = SKColor.black
63 | self.sizeLabel.horizontalAlignmentMode = .left
64 | // I don't know why but "self.sizeLabel.position.y = 25.0" causes a compile error
65 | self.sizeLabel.position = CGPoint(x: self.sizeLabel.position.x, y: 25.0)
66 |
67 | skScene.addChild(self.sizeLabel)
68 | }
69 |
70 | func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
71 | let (localMin, localMax) = self.trackingNode.boundingBox
72 | let min = self.trackingNode.convertPosition(localMin, to: nil)
73 | let max = self.trackingNode.convertPosition(localMax, to: nil)
74 | let vertices = [
75 | SCNVector3(min.x, min.y, min.z),
76 | SCNVector3(max.x, min.y, min.z),
77 | SCNVector3(min.x, max.y, min.z),
78 | SCNVector3(max.x, max.y, min.z),
79 | SCNVector3(min.x, min.y, max.z),
80 | SCNVector3(max.x, min.y, max.z),
81 | SCNVector3(min.x, max.y, max.z),
82 | SCNVector3(max.x, max.y, max.z)
83 | ]
84 | let arr = vertices.map { self.projectPoint($0) }
85 |
86 | let minX: CGFloat = arr.reduce(CGFloat.infinity, { $0 > $1.x ? $1.x : $0 })
87 | let minY: CGFloat = arr.reduce(CGFloat.infinity, { $0 > $1.y ? $1.y : $0 })
88 | //let minZ: CGFloat = arr.reduce(CGFloat.infinity, { $0 > $1.z ? $1.z : $0 })
89 | let maxX: CGFloat = arr.reduce(-CGFloat.infinity, { $0 < $1.x ? $1.x : $0 })
90 | let maxY: CGFloat = arr.reduce(-CGFloat.infinity, { $0 < $1.y ? $1.y : $0 })
91 | //let maxZ: CGFloat = arr.reduce(-CGFloat.infinity, { $0 < $1.z ? $1.z : $0 })
92 |
93 | let width = maxX - minX
94 | let height = maxY - minY
95 | //let depth = maxZ - minZ
96 |
97 | self.boundingBox.position = CGPoint(x: minX, y: minY)
98 | self.boundingBox.xScale = width / self.bbSize
99 | self.boundingBox.yScale = height / self.bbSize
100 |
101 | self.sizeLabel.text = "W: \(width), H: \(height)"
102 | }
103 | }
104 |
105 | let view = BBView()
106 |
107 | PlaygroundSupport.PlaygroundPage.current.liveView = view
108 | PlaygroundSupport.PlaygroundPage.current.needsIndefiniteExecution = true
109 |
110 |
--------------------------------------------------------------------------------
/BoundingBoxOnScreen.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/BoundingBoxOnScreen.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/BoundingBoxOnScreen.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SceneKitBoundingBoxOnScreen
2 | Xcode Playground to show how to calculate the size of the bounding box in screen space
3 |
4 | 
5 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magicien/SceneKitBoundingBoxOnScreen/088dba274143de3c94598217bb8ff116796eb746/screenshot.png
--------------------------------------------------------------------------------