SceneKit SCNPhysics车辆车轮指向车辆中心

SceneKit SCNPhysicsVehicle wheels point toward centre of vehicle

我正在尝试获取 SceneKit 物理载具 demonstration from WWDC working using Swift 2 and also the Scene Editor and .scnassets. I'm adapting this port of the demo to Swift 1.

我也一直在试验模型 I/O 的一些功能,例如天空盒和法线贴图生成。

一切正常,除了车轮绕其转向轴旋转 180 度,以便轮毂盖指向汽车的中心:

轮毂罩向内

车轮打滑方向正确,车子可以很好的行驶和转向,但就是看起来很奇怪(而且左右轴距比应有的窄)。

如果我注释掉 SCNPhysicsVehicle 和 SCNPhysicsVehicleWheel 代码,那么它只是带有底盘物理体的几何体,几何体显示正确,轮毂指向外:

轮毂罩朝外

我试过在定义 SCNPhysicsVehicleWheel 之前使用 wheelnode0.rotation 旋转轮节点,但没有效果。

我尝试用 wheel0.axle = SCNVector3(x: 1,y: 0,z: 0) 反转轮轴,这使得车轮朝向正确的方向,轮毂罩向外,(并且它们仍然以正确的方式旋转),但是汽车向后移动(即相反的方向轮子是如何旋转的)。

感觉坐标轴的翻译方式有点奇怪,但我不知道是什么。我已经尝试使用 Apple 演示中的原始 .dae 模型,并转换为 .scn 文件。我已经在 .scnassets 文件夹的内部和外部尝试过它(以防它与 scnassets 向上轴的自动更正有关)。我尝试反转车轮转向轴,但这只会导致车轮在空中指向上方。

这是我的车辆创建函数,我尝试过的所有内容都被注释掉了。完整的回购协议在这里:https://github.com/Utsira/SCNPhysicsVehicle-test。谁能看到这里出了什么问题?提前致谢。

func setupCar() -> SCNNode {
    let carScene = SCNScene(named: "art.scnassets/rc_car.scn") //rc_car.dae
    let chassisNode = carScene!.rootNode.childNodeWithName("rccarBody", recursively: true)!
    chassisNode.position = SCNVector3Make(0, 10, 30)
    //chassisNode.rotation = SCNVector4(0, 1, 0, CGFloat(M_PI))
    let body = SCNPhysicsBody.dynamicBody()
    body.allowsResting = false
    body.mass = 80
    body.restitution = 0.1
    body.friction = 0.5
    body.rollingFriction = 0
    chassisNode.physicsBody = body
    scnScene.rootNode.addChildNode(chassisNode)
     //getNode("rccarBody", fromDaePath: "rc_car.dae")
    let wheelnode0 = chassisNode
        .childNodeWithName("wheelLocator_FL", recursively: true)!
    let wheelnode1 = chassisNode
        .childNodeWithName("wheelLocator_FR", recursively: true)!
    let wheelnode2 = chassisNode
        .childNodeWithName("wheelLocator_RL", recursively: true)!
    let wheelnode3 = chassisNode
        .childNodeWithName("wheelLocator_RR", recursively: true)!

    //wheelnode0.geometry!.firstMaterial!.emission.contents = UIColor.blueColor()
    //        SCNTransaction.begin()
    //        wheelnode0.rotation = SCNVector4(x: 0, y: 1, z: 0, w: Float(M_PI)) //CGFloat(M_PI)
    //        wheelnode1.rotation = SCNVector4(x: 0, y: 1, z: 0, w: Float(M_PI))
    //        wheelnode2.rotation = SCNVector4(x: 0, y: 1, z: 0, w: Float(M_PI))
    //        wheelnode3.rotation = SCNVector4(x: 0, y: 1, z: 0, w: Float(M_PI))
    //        SCNTransaction.commit()
    //        wheelnode0.eulerAngles = SCNVector3Make(0, Float(M_PI), 0 )
    let wheel0 = SCNPhysicsVehicleWheel(node: wheelnode0)
    let wheel1 = SCNPhysicsVehicleWheel(node: wheelnode1)
    let wheel2 = SCNPhysicsVehicleWheel(node: wheelnode2)
    let wheel3 = SCNPhysicsVehicleWheel(node: wheelnode3)
    //        wheel0.steeringAxis = SCNVector3Make(0, -1, 1) //wheels point up in the air with 0,1,0
    //        wheel1.steeringAxis = SCNVector3Make(0, -1, 1)
    //        wheel2.steeringAxis = SCNVector3Make(0, -1, 1)
    //        wheel3.steeringAxis = SCNVector3Make(0, -1, 1)
    //        
    //        wheel0.axle = SCNVector3(x: 1,y: 0,z: 0) //wheels face and spin the right way, but car moves in opposite direction with 1,0,0
    //        wheel1.axle = SCNVector3(x: 1,y: 0,z: 0)
    //        wheel2.axle = SCNVector3(x: 1,y: 0,z: 0)
    //        wheel3.axle = SCNVector3(x: 1,y: 0,z: 0)
           // wheel0.steeringAxis = SCNVector3()
    //        var min = SCNVector3(x: 0, y: 0, z: 0)
    //        var max = SCNVector3(x: 0, y: 0, z: 0)
    //        wheelnode0.getBoundingBoxMin(&min, max: &max)
    //        let wheelHalfWidth = Float(0.5 * (max.x - min.x))
    //        var w0 = wheelnode0.convertPosition(SCNVector3Zero, toNode: chassisNode)
    //        w0 = w0 + SCNVector3Make(wheelHalfWidth, 0, 0)
    //        wheel0.connectionPosition = w0
    //        var w1 = wheelnode1.convertPosition(SCNVector3Zero, toNode: chassisNode)
    //        w1 = w1 - SCNVector3Make(wheelHalfWidth, 0, 0)
    //        wheel1.connectionPosition = w1
    //        var w2 = wheelnode2.convertPosition(SCNVector3Zero, toNode: chassisNode)
    //        w2 = w2 + SCNVector3Make(wheelHalfWidth, 0, 0)
    //        wheel2.connectionPosition = w2
    //        var w3 = wheelnode3.convertPosition(SCNVector3Zero, toNode: chassisNode)
    //        w3 = w3 - SCNVector3Make(wheelHalfWidth, 0, 0)
    //        wheel3.connectionPosition = w3

    vehicle = SCNPhysicsVehicle(chassisBody: chassisNode.physicsBody!,
                                wheels: [wheel0, wheel1, wheel2, wheel3])
    scnScene.physicsWorld.addBehavior(vehicle)
    return chassisNode

}

我找到了解决方案:

(但不是我希望的解决方案)

我的解决方法是将“FrontLeftWheel”的连接位置调整到最右边,以致于它充当了“FrontRightWheel”的角色。
而“FrontRightWheel”,靠左太多,以至于它扮演了“FrontLeftWheel”的角色。
我也为背部做了这个。

基本上,你有:

SCNVector3Make(wheelHalfWidth, 0, 0)

我将其替换为:

SCNVector3Make(wheelHalfWidth * 5.2, 0, 0)

但是,您可能不得不使用数字“5.2”来匹配您的 COLLADA (.dae)。

注:

别忘了替换:

 vehicle = SCNPhysicsVehicle(chassisBody: chassisNode.physicsBody!,
                            wheels: [wheel0, wheel1, wheel2, wheel3])

有:

 vehicle = SCNPhysicsVehicle(chassisBody: chassisNode.physicsBody!,
                            wheels: [wheel1, wheel0, wheel3, wheel2])

这样,当你使用 car.wheels[0].
你就得到了你期望的轮子

我认为你的问题是你没有为每个轮子设置连接位置。 Apple 的默认 ObjectiveC 代码很难转换为 swift.

wheel0.connectionPosition = SCNVector3FromFloat3(SCNVector3ToFloat3([wheel0Node convertPosition:SCNVector3Zero toNode:chassisNode]) + (vector_float3){wheelHalfWidth, 0.0, 0.0});
wheel1.connectionPosition = SCNVector3FromFloat3(SCNVector3ToFloat3([wheel1Node convertPosition:SCNVector3Zero toNode:chassisNode]) - (vector_float3){wheelHalfWidth, 0.0, 0.0});
wheel2.connectionPosition = SCNVector3FromFloat3(SCNVector3ToFloat3([wheel2Node convertPosition:SCNVector3Zero toNode:chassisNode]) + (vector_float3){wheelHalfWidth, 0.0, 0.0});
wheel3.connectionPosition = SCNVector3FromFloat3(SCNVector3ToFloat3([wheel3Node convertPosition:SCNVector3Zero toNode:chassisNode]) - (vector_float3){wheelHalfWidth, 0.0, 0.0});

翻译这四行(忽略重复)

let wheel0Position = wheel0Node.convertPosition(SCNVector3Zero, to: chassisNode)
let vector0Float3 = vector_float3(wheel0Position.x, wheel0Position.y, wheel0Position.z) + vector_float3(wheelHalfWidth, 0,0)
wheel0.connectionPosition = SCNVector3(vector0Float3.x, vector0Float3.y, vector0Float3.z)

let wheel1Position = wheel1Node.convertPosition(SCNVector3Zero, to: chassisNode)
let vector1Float3 = vector_float3(wheel1Position.x, wheel1Position.y, wheel1Position.z) - vector_float3(wheelHalfWidth, 0,0)
wheel1.connectionPosition = SCNVector3(vector1Float3.x, vector1Float3.y, vector1Float3.z)

let wheel2Position = wheel2Node.convertPosition(SCNVector3Zero, to: chassisNode)
let vector2Float3 = vector_float3(wheel2Position.x, wheel2Position.y, wheel2Position.z) + vector_float3(wheelHalfWidth, 0,0)
wheel2.connectionPosition = SCNVector3(vector2Float3.x, vector2Float3.y, vector2Float3.z)

let wheel3Position = wheel3Node.convertPosition(SCNVector3Zero, to: chassisNode)
let vector3Float3 = vector_float3(wheel3Position.x, wheel3Position.y, wheel3Position.z) - vector_float3(wheelHalfWidth, 0,0)
wheel3.connectionPosition = SCNVector3(vector3Float3.x, vector3Float3.y, vector3Float3.z)

通过添加或减去 vector_float3,轮子定位在正确的位置。

此外,请记住您不能在场景中缩放节点,否则可能会发生奇怪的事情。

遇到同样的问题,我的解决办法是旋转所有轮子节点,使Y轴指向下方。我认为重力是向下的力。