Home > front end >  SceneKit – SCNPhysicsVehicle wheels facing inwards (90 degrees)
SceneKit – SCNPhysicsVehicle wheels facing inwards (90 degrees)

Time:04-01

I am attempting to create a SCNPhysicsVehicle using SceneKit. The vehicle drives using the applyEngineForce method.

In my Scene Graph, my vehicle looks like the screenshot below. However, when I build the project, the wheels rotate 90 degrees about the y axis. The vehicle and wheel physics work correctly, only that the wheels are facing the wrong direction.

I have tried defining the wheel connectionPosition, however was unsuccessful. Also, I have tried defining wheelNode.rotate and wheel0.axle, all to no avail.

Would you please shed some light?

enter image description here

func setUpCar() {
    
    let chassisNode = scene!.rootNode.childNode(withName: "car", recursively: true)!
    
    let body = SCNPhysicsBody.dynamic()
        body.allowsResting = false
        body.mass = 80
        body.restitution = 0.1
        body.friction = 0.5
        body.rollingFriction = 0
        chassisNode.physicsBody = body
        scene.rootNode.addChildNode(chassisNode)
    
    // Add Wheels
    let wheelnode0 = chassisNode.childNode(withName: "wheelLocator_FL", recursively: true)!
    let wheelnode1 = chassisNode.childNode(withName: "wheelLocator_FR", recursively: true)!
    let wheelnode2 = chassisNode.childNode(withName: "wheelLocator_RL", recursively: true)!
    let wheelnode3 = chassisNode.childNode(withName: "wheelLocator_RR", recursively: true)!
    let wheel0 = SCNPhysicsVehicleWheel(node: wheelnode0)
    let wheel1 = SCNPhysicsVehicleWheel(node: wheelnode1)
    let wheel2 = SCNPhysicsVehicleWheel(node: wheelnode2)
    let wheel3 = SCNPhysicsVehicleWheel(node: wheelnode3)
    let min = SCNVector3(x: 0, y: 0, z: 0)
    let max = SCNVector3(x: 0, y: 0, z: 0)
    wheelnode0.boundingBox.max = max
    wheelnode0.boundingBox.min = min
    
    // Wheel Axle
    //wheel0.axle = SCNVector3(x: 1,y: 0,z: 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)
    
    // Wheel Rotation
    //wheelnode0.rotation = SCNVector4(x: 0, y: 1, z: 0, w: Float(Double.pi)) //CGFloat(M_PI)
    //wheelnode1.rotation = SCNVector4(x: 0, y: 1, z: 0, w: Float(Double.pi))
    //wheelnode2.rotation = SCNVector4(x: 0, y: 1, z: 0, w: Float(Double.pi))
    //wheelnode3.rotation = SCNVector4(x: 0, y: 1, z: 0, w: Float(Double.pi))
    
     
    let wheelHalfWidth = Float(0.5 * (max.x - min.x))
    SCNVector3Make(wheelHalfWidth * 5.2, 0, 0)
    
    /*
    // Connet Wheels to Chasis
    let wheel0Position = wheelnode0.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 = wheelnode1.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 = wheelnode2.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 = wheelnode3.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)
    */

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

}

CodePudding user response:

You need to control a steering vector. The default values of steering axis are [0,-1, 0].

var steeringAxis: SCNVector3 { get set }

There is setSteeringAngle(_:forWheelAt:) instance method that allows you control the direction of the wheel at the specified index. The steering value is expressed in radian, 0 means straight ahead (a.k.a. neutral steering).

func setSteeringAngle(_ value: CGFloat, forWheelAt index: Int)

Steering angles are relative to the wheel’s steeringAxis vector. With the default steering axis of [0.0,-1.0, 0.0] (it's obvious that the multiplier is .pi/2), positive values steer the vehicle to the right, and negative values steer to the left.

CodePudding user response:

Highly appreciate the help Andy, but I'm not sure that I understand. I have managed to get the wheels facing in the correct direction, using:

wheel0.axle = SCNVector3(x: 0,y: 0,z: 1)
wheel1.axle = SCNVector3(x: 0,y: 0,z: 1)
wheel2.axle = SCNVector3(x: 0,y: 0,z: 1)
wheel3.axle = SCNVector3(x: 0,y: 0,z: 1)

However, the wheels still turn head over heals, in this case each side, left and right wheels both turning towards the chassis.

It appears that the steeringAxis is correct, because the wheels are steering as they should. See images:

Turn Right

Turn Left

  • Related