首页 文章

SceneKit SCNPhysicsVehicle 车轮指向车辆中心

提问于
浏览
2

我正在尝试使用 Swift 2 以及场景编辑器和.scnassets 来使 SceneKit Physics Vehicle 来自 WWDC 的演示工作。我正在适应Swift 1 演示的这个端口。

我也一直在试验一些 Model I/O 函数,比如 SkyBox 和普通的地图生成。

一切都很好,除了轮子绕转向轴旋转 180 度,以便轮毂盖指向汽车的中心:

轮毂盖向内
Hubcaps 指向内部

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

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

轮毂盖指向外面
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

    我找到了解决方案:

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

    我的修复方法是将“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 [9]时。
    你得到了你期待的轮子

  • 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,车轮定位在正确的位置。

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

  • 0

    遇到同样的问题,我的解决方案是旋转所有轮节点,使 Y 轴指向下方。我认为引力是一种向下的力量。

相关问题