将ARSCNView Aspect中的大型3d Object.scn文件加载到屏幕ARKIT Swift iOS中

将ARSCNView Aspect中的大型3d Object.scn文件加载到屏幕ARKIT Swift iOS中,ios,swift,augmented-reality,arkit,scnnode,Ios,Swift,Augmented Reality,Arkit,Scnnode,我正在使用3d模型开发ARKit应用程序。因此,我使用了3d模型,并为移动、旋转和缩放3d模型添加了手势 现在我只面临一个问题,但我不确定这个问题是否与什么有关。3d模型中是否存在问题,或者我的程序中是否缺少任何内容 问题是我使用的3d模型显示的非常大,超出了屏幕。我试图缩小它的尺寸,但它非常大 这是我的代码: @IBOutlet var mySceneView: ARSCNView! var selectedNode = SCNNode() var prevLoc = CGPoint() va

我正在使用3d模型开发ARKit应用程序。因此,我使用了3d模型,并为移动、旋转和缩放3d模型添加了手势

现在我只面临一个问题,但我不确定这个问题是否与什么有关。3d模型中是否存在问题,或者我的程序中是否缺少任何内容

问题是我使用的3d模型显示的非常大,超出了屏幕。我试图缩小它的尺寸,但它非常大

这是我的代码:

@IBOutlet var mySceneView: ARSCNView!
var selectedNode = SCNNode()
var prevLoc = CGPoint()
var touchCount : Int = 0

override func viewDidLoad() {
    super.viewDidLoad()
    self.lblTitle.text = self.sceneTitle
    let mySCN = SCNScene.init(named: "art.scnassets/\(self.sceneImagename).scn")!
    self.mySceneView.scene = mySCN

    let cameraNode = SCNNode()
    cameraNode.camera = SCNCamera()
    cameraNode.position = SCNVector3Make(0, 0, 0)
    self.mySceneView.scene.rootNode.addChildNode(cameraNode)
    self.mySceneView.allowsCameraControl = true
    self.mySceneView.autoenablesDefaultLighting = true

    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(detailPage.doHandleTap(_:)))
    let panGesture = UIPanGestureRecognizer(target: self, action: #selector(detailPage.doHandlePan(_:)))
    let gesturesArray = NSMutableArray()
    gesturesArray.add(tapGesture)
    gesturesArray.add(panGesture)
    gesturesArray.addObjects(from: self.mySceneView.gestureRecognizers!)
    self.mySceneView.gestureRecognizers = (gesturesArray as! [UIGestureRecognizer])
}

//MARK:- Handle Gesture
@objc func doHandlePan(_ sender: UIPanGestureRecognizer) {
    var delta = sender.translation(in: self.view)
    let loc = sender.location(in: self.view)
    if sender.state == .began {
        self.prevLoc = loc
        self.touchCount = sender.numberOfTouches
    } else if sender.state == .changed {
        delta = CGPoint(x: loc.x - prevLoc.x, y: loc.y - prevLoc.y)
        prevLoc = loc
        if self.touchCount != sender.numberOfTouches {
            return
        }

        var rotMat = SCNMatrix4()
        if touchCount == 2 {
            rotMat = SCNMatrix4MakeTranslation(Float(delta.x * 0.025), Float(delta.y * -0.025), 0)
        } else {
            let rotMatX = SCNMatrix4Rotate(SCNMatrix4Identity, Float((1.0/100) * delta.y), 1, 0, 0)
            let rotMatY = SCNMatrix4Rotate(SCNMatrix4Identity, Float((1.0/100) * delta.x), 0, 1, 0)
            rotMat = SCNMatrix4Mult(rotMatX, rotMatY)
        }

        let transMat = SCNMatrix4MakeTranslation(selectedNode.position.x, selectedNode.position.y, selectedNode.position.z)
        selectedNode.transform = SCNMatrix4Mult(selectedNode.transform, SCNMatrix4Invert(transMat))

        let parentNodeTransMat = SCNMatrix4MakeTranslation((selectedNode.parent?.worldPosition.x)!, (selectedNode.parent?.worldPosition.y)!, (selectedNode.parent?.worldPosition.z)!)
        let parentNodeMatWOTrans = SCNMatrix4Mult(selectedNode.parent!.worldTransform, SCNMatrix4Invert(parentNodeTransMat))
        selectedNode.transform = SCNMatrix4Mult(selectedNode.transform, parentNodeMatWOTrans)

        let camorbitNodeTransMat = SCNMatrix4MakeTranslation((self.mySceneView.pointOfView?.worldPosition.x)!, (self.mySceneView.pointOfView?.worldPosition.y)!, (self.mySceneView.pointOfView?.worldPosition.z)!)
        let camorbitNodeMatWOTrans = SCNMatrix4Mult(self.mySceneView.pointOfView!.worldTransform, SCNMatrix4Invert(camorbitNodeTransMat))
        selectedNode.transform = SCNMatrix4Mult(selectedNode.transform, SCNMatrix4Invert(camorbitNodeMatWOTrans))
        selectedNode.transform = SCNMatrix4Mult(selectedNode.transform, rotMat)

        selectedNode.transform = SCNMatrix4Mult(selectedNode.transform, camorbitNodeMatWOTrans)
        selectedNode.transform = SCNMatrix4Mult(selectedNode.transform, SCNMatrix4Invert(parentNodeMatWOTrans))
        selectedNode.transform = SCNMatrix4Mult(selectedNode.transform, transMat)
    }
}

@objc func doHandleTap(_ sender: UITapGestureRecognizer) {
    let p = sender.location(in: self.mySceneView)
    var hitResults = self.mySceneView.hitTest(p, options: nil)

    if (p.x > self.mySceneView.frame.size.width-100 || p.y < 100) {
        self.mySceneView.allowsCameraControl = !self.mySceneView.allowsCameraControl
    }

    if hitResults.count > 0 {
        let result = hitResults[0]
        let material = result.node.geometry?.firstMaterial
        selectedNode = result.node

        SCNTransaction.begin()
        SCNTransaction.animationDuration = 0.3

        SCNTransaction.completionBlock = {
            SCNTransaction.begin()
            SCNTransaction.animationDuration = 0.3
            SCNTransaction.commit()
        }
        material?.emission.contents = UIColor.white
        SCNTransaction.commit()
    }
}
@IBOutlet var mySceneView:ARSCNView!
var selectedNode=SCNNode()
var prevLoc=CGPoint()
var-touchCount:Int=0
重写func viewDidLoad(){
super.viewDidLoad()
self.lblTitle.text=self.sceneTitle
让mySCN=SCNScene.init(名为:“art.scnassets/\(self.sceneImagename.scn”)!
self.mySceneView.scene=mySCN
让cameraNode=SCNNode()
cameraNode.camera=SCNCamera()
cameraNode.position=SCInvector3Make(0,0,0)
self.mySceneView.scene.rootNode.addChildNode(cameraNode)
self.mySceneView.allowsCameraControl=true
self.mySceneView.autoenablesdfaultlighting=true
让TapSirture=UITapGestureRecognizer(目标:自我,操作:#选择器(detailPage.doHandleTap(:))
让pangestrue=ui pangestruerecognizer(目标:self,操作:#选择器(detailPage.doHandlePan(:))
设gesturesArray=NSMutableArray()
添加(点击手势)
gesturesArray.add(panGesture)
gesturesArray.addObjects(来自:self.mySceneView.GestureRecograiners!)
self.mySceneView.gestureerecognizers=(gesturesArray作为![uigestureerecognizer])
}
//马克:-把手手势
@objc func doHandlePan(uu发送方:UIPANGESTURE识别器){
var delta=sender.translation(在:self.view中)
让loc=sender.location(在:self.view中)
如果sender.state==。开始{
self.prevLoc=loc
self.touchCount=sender.numberoftouchs
}否则,如果sender.state==。已更改{
delta=CGPoint(x:loc.x-prevLoc.x,y:loc.y-prevLoc.y)
prevLoc=loc
如果self.touchCount!=sender.numberoftouchs{
返回
}
var rotMat=SCNMatrix4()
如果touchCount==2{
rotMat=SCNMATRIX4MAKETRANSACTION(浮点(delta.x*0.025)、浮点(delta.y*-0.025)、0)
}否则{
让rotMatX=scnmatrix4旋转(SCNMatrix4Identity,Float((1.0/100)*delta.y),1,0,0)
让rotMatY=scnmatrix4旋转(SCNMatrix4Identity,Float((1.0/100)*delta.x),0,1,0)
rotMat=SCNMatrix4Mult(rotMatX,rotMatY)
}
让transMat=scnmarix4maketranslation(selectedNode.position.x,selectedNode.position.y,selectedNode.position.z)
selectedNode.transform=SCNMatrix4Mult(selectedNode.transform,SCNMatrix4Invert(transMat))
让parentNodeTransMat=SCNMATRIX4生成转换((selectedNode.parent?.worldPosition.x)!,(selectedNode.parent?.worldPosition.y)!,(selectedNode.parent?.worldPosition.z)!)
让ParentNodeMatowTrans=SCNMatrix4Mult(selectedNode.parent!.worldTransform,SCNMatrix4Invert(parentNodeTransMat))
selectedNode.transform=SCNMatrix4Mult(selectedNode.transform,parentNodeMatWOTrans)
让camorbitNodeTransMat=SCNMATRIX4进行翻译((self.mySceneView.pointOfView?.worldPosition.x)!,(self.mySceneView.pointOfView?.worldPosition.y)!,(self.mySceneView.pointOfView?.worldPosition.z)!)
让CamorbitNodeManageTrans=SCNMatrix4Mult(self.mySceneView.pointOfView!.worldTransform,SCNMatrix4Invert(camorbitNodeTransMat))
selectedNode.transform=SCNMatrix4Mult(selectedNode.transform,SCNMatrix4Invert(CamorbitNodeManageTrans))
selectedNode.transform=SCNMatrix4Mult(selectedNode.transform,rotMat)
selectedNode.transform=SCNMatrix4Mult(selectedNode.transform,CamorbitNodeMatoTrans)
selectedNode.transform=SCNMatrix4Mult(selectedNode.transform,SCNMatrix4Invert(ParentNodeManageTrans))
selectedNode.transform=SCNMatrix4Mult(selectedNode.transform,transMat)
}
}
@objc func doHandleTap(\发送方:UITAPPgestureRecognitizer){
设p=sender.location(在:self.mySceneView中)
var hitResults=self.mySceneView.hitTest(p,选项:nil)
如果(p.x>self.mySceneView.frame.size.width-100 | | p.y<100){
self.mySceneView.allowsCameraControl=!self.mySceneView.allowsCameraControl
}
如果hitResults.count>0{
let result=hitResults[0]
让material=result.node.geometry?.firstMaterial
selectedNode=result.node
SCNTransaction.begin()
SCNTransaction.animationDuration=0.3
SCNTransaction.completionBlock={
SCNTransaction.begin()
SCNTransaction.animationDuration=0.3
SCNTransaction.commit()
}
材料?.emission.contents=UIColor.white
SCNTransaction.commit()
}
}
我的问题是:

我们可以在屏幕中央设置任何尺寸的3d对象模型方面与屏幕尺寸相匹配吗?请建议是否有办法


任何指导或建议都将不胜感激。

您需要的是获得边界球体大小,然后可以将其投影到屏幕上。或者,获取该半径与scenekit摄影机和对象位置之间距离的比率。通过这种方式,您将知道对象在屏幕上的显示大小。要缩小比例,只需设置对象的
scale
属性


对于第二部分,您可以使用。

我处理此问题的方法是确保3D模型始终具有固定大小

例如,如果三维模型是一个小杯子或一座大房子,我确保它在场景坐标空间上的宽度始终为25厘米(同时保持x和y和z之间的比率)

可以按如下方式计算节点边界框的宽度:

let mySCN = SCNScene(named: "art.scnassets/\(self.sceneImagename).scn")!

let minX = mySCN.rootNode.boundingBox.min.x
let maxX = mySCN.rootNode.boundingBox.max.x

// change 0.25 to whatever you need
// this value is in meters
let scaleValue = 0.25 / abs(minX - maxX)

// scale all axes of the node using `scaleValue`
// this maintains ratios and does not stretch the model
mySCN.rootNode.scale = SCNVector3(scaleValue, scaleValue, scaleValue)

self.mySceneView.scene = mySCN
也可以使用y或z v基于高度或深度计算比例值