我创建了一个模型(例如,使用四面墙构建)并使用Sketchup将其导出为.dea文件。后来我在现场添加了tap guest,并找出了场景中的哪个墙被点击了。我得到了结果 - 墙的确切名称(id),但我没有得到这个位置。位置总是 - (x:0,y:0,z:0)。我想在我拍摄的每个墙上添加一个新的SCNNode,所以我需要在场景中准确定位墙壁。
截图:
如截图所示,我点击了第一栋建筑的前侧墙,但结果为零矢量。
我在stackOverflow和Internet上也尝试了所有解决方案,但没有成功。有人能帮助我吗?
dae文件:
http://www.filefactory.com/file/40y2ef86hgm3/Sample3d.dae
代码:
import UIKit
import QuartzCore
import SceneKit
import SpriteKit
import AVFoundation
class SceneViewController: UIViewController, UIGestureRecognizerDelegate {
//Data handlers
var currentSceneView: SCNView? = nil
var cameraOrbit = SCNNode()
let cameraNode = SCNNode()
let camera = SCNCamera()
var sceneText = SCNText()
//HANDLE PAN CAMERA
var lastWidthRatio: Float = 0
var lastHeightRatio: Float = 0.2
var WidthRatio: Float = 0
var HeightRatio: Float = 0.2
var fingersNeededToPan = 1
var maxWidthRatioRight: Float = 0.2
var maxWidthRatioLeft: Float = -0.2
var maxHeightRatioXDown: Float = 0.02
var maxHeightRatioXUp: Float = 0.4
//HANDLE PINCH CAMERA
var pinchAttenuation = 20.0 //1.0: very fast ---- 100.0 very slow
var lastFingersNumber = 0
var myScene = SCNScene()
// MARK: - View Lifecycle methods
override func viewDidLoad() {
super.viewDidLoad()
// create a new scene
let scene = SCNScene(named: "Sample3d.dae")!
myScene = scene
addCameraNode(scene: scene)
prepareScene(scene: scene)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
// MARK: - Private APIs
func addCameraNode(scene : SCNScene){
// create and add a camera to the scene
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
// place the camera
cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
// create and add a light to the scene
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = SCNLight.LightType.omni
lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
// scene.rootNode.addChildNode(lightNode)
cameraNode.addChildNode(lightNode)
// create and add an ambient light to the scene
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = SCNLight.LightType.ambient
ambientLightNode.light!.color = UIColor.darkGray
// scene.rootNode.addChildNode(ambientLightNode)
cameraNode.addChildNode(ambientLightNode)
//Create a camera like Rickster said
camera.usesOrthographicProjection = true
camera.orthographicScale = 1
//camera.orthographicScale = 100
camera.zNear = 1
camera.zFar = 100
cameraNode.position = SCNVector3(x: 0, y: 0, z: 20)
cameraNode.camera = camera
cameraOrbit = SCNNode()
cameraOrbit.addChildNode(cameraNode)
scene.rootNode.addChildNode(cameraOrbit)
}
func prepareScene(scene : SCNScene){
self.navigationItem.title = "3D Scene"
//initial camera setup
self.cameraOrbit.eulerAngles.y = Float(-3 * M_PI) * lastWidthRatio
self.cameraOrbit.eulerAngles.x = Float(-M_PI) * lastHeightRatio
// retrieve the SCNView
let scnView = self.view as! SCNView
currentSceneView = scnView
// set the scene to the view
scnView.scene = scene
// allows the user to manipulate the camera
scnView.allowsCameraControl = true
// show statistics such as fps and timing information
scnView.showsStatistics = true
// configure the view
scnView.backgroundColor = UIColor.black
//allows the user to manipulate the camera
scnView.allowsCameraControl = false //not needed
// add a tap gesture recognizer
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(SceneViewController.handlePan(_:)))
scnView.addGestureRecognizer(panGesture)
// add a pinch gesture recognizer
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(SceneViewController.handlePinch(_:)))
scnView.addGestureRecognizer(pinchGesture)
let tap = UITapGestureRecognizer(target: self, action: #selector(SceneViewController.handleTap(_:)))
tap.delegate = self
scnView.addGestureRecognizer(tap)
}
// MARK: - Guesture Recognition methods
func handleTap(_ gestureRecognize: UIGestureRecognizer) {
let location: CGPoint = gestureRecognize.location(in: currentSceneView)// for example from a tap gesture recognizer
let hits = self.currentSceneView?.hitTest(location, options: nil)
if let tappedNode = hits?.first?.node {
addVideoNodeToScene(presentNode: tappedNode)
}
}
func addVideoNodeToScene(presentNode: SCNNode){
if let path = Bundle.main.path(forResource: "Sample", ofType: "mp4") {
let videoUrl = NSURL(fileURLWithPath: path)
let player = AVPlayer(url: videoUrl as URL)
let videoNode = SKVideoNode(avPlayer: player)
let size = CGSize(width: 1024, height: 512)
videoNode.size = size
videoNode.position = CGPoint(x: size.width/2.0,y :size.height/2.0)
let spriteScene = SKScene(size: size)
spriteScene.addChild(videoNode)
let cubeMaterial = SCNMaterial()
cubeMaterial.diffuse.contents = spriteScene
cubeMaterial.isDoubleSided = true
let v1 = SCNVector3(x: 0,y: 0,z: 0)
let v2 = SCNVector3(x: 0,y: 0,z: 0)
let dx:Float = Float(v1.x - v2.x)/2.0
let dy:Float = Float(v1.y - v2.y)
var plane = SCNPlane()
plane = SCNPlane.init(width: 0.35, height: 0.35)
let planeNode = SCNNode(geometry: plane)
plane.firstMaterial?.isDoubleSided = true
planeNode.rotation = SCNVector4(x: 0, y: 0, z: 1, w: Float(M_PI))
planeNode.geometry?.firstMaterial = cubeMaterial
planeNode.position = presentNode.position
planeNode.position.z = planeNode5.position.z + 0.15
myScene.rootNode.addChildNode(planeNode)
videoNode.play()
}
}
func handlePan(_ gestureRecognize: UIPanGestureRecognizer) {
let numberOfTouches = gestureRecognize.numberOfTouches
let translation = gestureRecognize.translation(in: gestureRecognize.view!)
if (numberOfTouches==fingersNeededToPan) {
WidthRatio = Float(translation.x) / Float(gestureRecognize.view!.frame.size.width) + lastWidthRatio
HeightRatio = Float(translation.y) / Float(gestureRecognize.view!.frame.size.height) + lastHeightRatio
// HEIGHT constraints
if (HeightRatio >= maxHeightRatioXUp ) {
HeightRatio = maxHeightRatioXUp
}
if (HeightRatio <= maxHeightRatioXDown ) {
HeightRatio = maxHeightRatioXDown
}
// WIDTH constraints
if(WidthRatio >= maxWidthRatioRight) {
WidthRatio = maxWidthRatioRight
}
if(WidthRatio <= maxWidthRatioLeft) {
WidthRatio = maxWidthRatioLeft
}
self.cameraOrbit.eulerAngles.y = Float(-5 * M_PI) * WidthRatio
self.cameraOrbit.eulerAngles.x = Float(-2 * M_PI) * HeightRatio
//print("Height: \(round(HeightRatio*100))")
//print("Width: \(round(WidthRatio*100))")
//for final check on fingers number
lastFingersNumber = fingersNeededToPan
}
lastFingersNumber = (numberOfTouches>0 ? numberOfTouches : lastFingersNumber)
if (gestureRecognize.state == .ended && lastFingersNumber==fingersNeededToPan) {
lastWidthRatio = WidthRatio
lastHeightRatio = HeightRatio
//print("Pan with \(lastFingersNumber) finger\(lastFingersNumber>1 ? "s" : "")")
}
}
func handlePinch(_ gestureRecognize: UIPinchGestureRecognizer) {
let pinchVelocity = Double.init(gestureRecognize.velocity)
//print("PinchVelocity \(pinchVelocity)")
camera.orthographicScale -= (pinchVelocity/pinchAttenuation)
//print("PinchVelocity \(camera.orthographicScale)")
if camera.orthographicScale <= 0.5 {
camera.orthographicScale = 0.5
}
if camera.orthographicScale >= 5 {
camera.orthographicScale = 5
}
}
// MARK: - ViewController Orientation methods
override var shouldAutorotate : Bool {
return true
}
override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
if UIDevice.current.userInterfaceIdiom == .phone {
return .allButUpsideDown
} else {
return .all
}
}
// MARK: - Status bar methods
override var prefersStatusBarHidden : Bool {
return true
}
}
答案 0 :(得分:1)
在您附加的文件中,每个节点都位于(0, 0, 0)
上,但具有不同的euler angle
。正如我正在检查其他3D模型,你的代码工作得非常好。联系您的3D设计师并让他/她修复模型。
我建议您在编辑器(Xcode)中打开dae
,将每个euler angle
设为(0, 0, 0)
,并根据要求更改节点的位置。