SceneKit SCNPhysicsVehicle车轮指向车辆中心

时间:2016-04-24 21:28:36

标签: swift scenekit

我正在尝试使用Swift 2以及场景编辑器和.scnassets来使SceneKit物理工具demonstration from WWDC正常工作。我正在调整this port of the demo to Swift 1.

我也在尝试一些模型I / O函数,例如SkyBox和法线贴图生成。

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

hubcaps pointing inward Hubcaps指向内部

车轮在正确的方向旋转,车辆可以被驱动和转向很好,但它看起来非常奇怪(左右轴距比它应该更窄)。

如果我注释掉SCNPhysicsVehicle和SCNPhysicsVehicleWheel代码,那么它只是几何体与机箱的物理主体,几何图形正确显示,轮毂指向外:

hubcaps pointing outward Hubcaps指向外面

在定义SCNPhysicsVehicleWheel之前,我尝试使用wheelnode0.rotation旋转wheelnodes,但它没有效果。

我尝试用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

}

3 个答案:

答案 0 :(得分:0)

我找到了一个解决方案:

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

我的解决方法是调整“FrontLeftWheel”的connectionPosition,向右调整,它扮演“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]时。你得到了你期待的轮子

答案 1 :(得分: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,轮子位于正确的位置。

另外,请记住,您无法在场景中缩放节点,或者可能发生奇怪的事情。

答案 2 :(得分:0)

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