如何快速地沿着车轮移动车身?

时间:2018-05-15 09:10:53

标签: ios swift arkit

我一直试图将车身与车轮一起移动。我创建了增强现实项目,将汽车模型放置在水平面上,汽车由四个按钮控制,即加速,转向,倒车和制动。汽车左,右是控制器通过转向加速和反转。

实际上现在我可以将3D汽车模型放在水平面上,但不知道如何像车身那样向前和向后旋转车轮。

以下是我尝试放置3d对象的代码:

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    if let touch = touches.first {

        // gives us the location of where we touched on the 2D screen.
        let touchLocation = touch.location(in: sceneView)

        // hitTest is performed to get the 3D coordinates corresponding to the 2D coordinates that we got from touching the screen.
        // That 3d coordinate will only be considered when it is on the existing plane that we detected.
        let results = sceneView.hitTest(touchLocation, types: .existingPlaneUsingExtent)

        // if we have got some results using the hitTest then do this.
        if let hitResult = results.first {


           let boxScene = SCNScene(named: "art.scnassets/porsche.scn")!

            if let boxNode = boxScene.rootNode.childNode(withName: "car", recursively: true) {
                print("box:::\(boxNode.childNodes)")

                boxNode.position = SCNVector3(x: hitResult.worldTransform.columns.3.x, y: hitResult.worldTransform.columns.3.y + 0.15, z: hitResult.worldTransform.columns.3.z)

                // finally the box is added to the scene.
                sceneView.scene.rootNode.addChildNode(boxNode)

            }


        }

    }
}

检测水平面功能代码:

   func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

    if anchor is ARPlaneAnchor {

        // anchors can be of many types, as we are just dealing with horizontal plane detection we need to downcast anchor to ARPlaneAnchor
        let planeAnchor = anchor as! ARPlaneAnchor

        // creating a plane geometry with the help of dimentions we got using plane anchor.
        let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z))

        // a node is basically a position.
        let planeNode = SCNNode()

        // setting the position of the plane geometry to the position we got using plane anchor.
        planeNode.position = SCNVector3(x: planeAnchor.center.x, y: 0, z: planeAnchor.center.z)

        // when a plane is created its created in xy plane instead of xz plane, so we need to rotate it along x axis.
        planeNode.transform = SCNMatrix4MakeRotation(-Float.pi/2, 1, 0, 0)

        //create a material object
        let gridMaterial = SCNMaterial()

        //setting the material as an image. A material can also be set to a color.
        gridMaterial.diffuse.contents = UIImage(named: "art.scnassets/grid.png")

        // assigning the material to the plane
        plane.materials = [gridMaterial]


        // assigning the position to the plane
        planeNode.geometry = plane

        //adding the plane node in our scene
        node.addChildNode(planeNode)



    }

    else {

        return
    }

}

任何帮助都非常感谢!!!

1 个答案:

答案 0 :(得分:16)

这是一项非常全面的任务。

你应该把你的车当作SCNPhysicsVehicle的子类。

SCNPhysicsVehicle是一种物理行为,可以修改物理主体,使其表现得像汽车,摩托车或其他轮式车辆。

要构建车辆,请将SCNPhysicsBody对象指定为其底盘,并将SCNPhysicsVehicleWheel对象的数组指定为其车轮。对于每个车轮,您可以定义物理特性(例如悬架和牵引力),并关联场景中的节点以提供车轮尺寸和视觉表示。在构建车辆后,您可以在加速,制动和转向方面对其进行控制。

将军:https://developer.apple.com/documentation/scenekit/scnphysicsbody

对于轮子:https://developer.apple.com/documentation/scenekit/scnphysicsvehiclewheel

示例:

var vehicle = SCNPhysicsVehicle()
  1. 您需要使用静态物体创建地面。

    func createGround(planeAnchor: ARPlaneAnchor) -> SCNNode {
       let ground = SCNNode(geometry: SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(CGFloat(planeAnchor.extent.z))))
       ground.position = SCNVector3(planeAnchor.center.x,planeAnchor.center.y,planeAnchor.center.z)
       ground.eulerAngles = SCNVector3(90.degreesToRadians, 0, 0)
       let staticBody = SCNPhysicsBody.static() // it must be static
       ground.physicsBody = staticBody
       return ground
       }
    
  2. 您需要设置汽车。

    func setupCar() {
    
    let scene = SCNScene(named: "YourScene.scn")
    let chassis = (scene?.rootNode.childNode(withName: "chassis", recursively: true))! // Your chassis
    let frontLeftWheel = chassis.childNode(withName: "frontLeftWheel", recursively: true)!
    let frontRightWheel = chassis.childNode(withName: "frontRightWheel", recursively: true)!
    let rearLeftWheel = chassis.childNode(withName: "rearLeftWheel", recursively: true)!
    let rearRightWheel = chassis.childNode(withName: "rearRightWheel", recursively: true)!
    
    // physic behavior for wheels
    
    let v_frontLeftWheel = SCNPhysicsVehicleWheel(node: frontLeftWheel)
    let v_frontRightWheel = SCNPhysicsVehicleWheel(node: frontRightWheel)
    let v_rearRightWheel = SCNPhysicsVehicleWheel(node: rearLeftWheel)
    let v_rearLeftWheel = SCNPhysicsVehicleWheel(node: rearRightWheel)
    
    
    chassis.position = SCNVector(0,0,0) // insert your desired position
    let body = SCNPhysicsBody(type: .dynamic, shape: SCNPhysicsShape(node: chassis, options: [SCNPhysicsShape.Option.keepAsCompound: true]))
    body.mass = 1
    chassis.physicsBody = body
    self.vehicle = SCNPhysicsVehicle(chassisBody: chassis.physicsBody!, wheels: [v_rearRightWheel, v_rearLeftWheel, v_frontRightWheel, v_frontLeftWheel])
    self.sceneView.scene.physicsWorld.addBehavior(self.vehicle)
    self.sceneView.scene.rootNode.addChildNode(chassis)
    }
    
    1. 现在你可以用你的车操纵了。

       func renderer(_ renderer: SCNSceneRenderer, didSimulatePhysicsAtTime time: TimeInterval) {
      
       var engineForce: CGFloat = 5
       var brakingForce: CGFloat = 0
      
       // here you can manipulate your car steering angle
       self.vehicle.setSteeringAngle(0, forWheelAt: 2) 
       self.vehicle.setSteeringAngle(0, forWheelAt: 3)
      
      
       self.vehicle.applyEngineForce(engineForce, forWheelAt: 0)
       self.vehicle.applyEngineForce(engineForce, forWheelAt: 1)
       self.vehicle.applyBrakingForce(0, forWheelAt: 0)
       self.vehicle.applyBrakingForce(0, forWheelAt: 1)
       }
      
  3. P.S。别忘了添加到viewDidLoad():

            self.sceneView.delegate = self
            self.sceneView.scene?.physicsWorld.contactDelegate = self
    

    P.P.S这只是一般性的想法,你必须做一些研究,找到适合你特定情况的工作方案。

    给你一点提示,可以通过CoreMotion完成转向。

    我希望它有所帮助!