Колеса в воздухе с SCNPhsysicsТранспорт с ARKit - PullRequest
0 голосов
/ 18 апреля 2020

Я делаю AR-игру, используя ARKit и SceneKit (поскольку единственный способ симулировать автомобиль - это SCNPhysicsVehicle). Я сделал «машину», используя коробку и 4 цилиндра, и если «колеса» расположены под коробкой (заданной как кузов автомобиля или шасси), она работает отлично! Но если я поверну колеса, чтобы они были больше похожи на настоящее колесо, расположенное сбоку от тела, когда я запустил сцену AR, колеса окажутся на 1 метр выше тела!

Плюс, я никогда не смог чтобы сделать эту работу с помощью 3D-модели. Иногда колеса появляются на расстоянии 20 см под машиной, и через секунду все улетает. Если я изменю ось Y на отрицательную, шасси будет работать как положено, но колеса появятся над автомобилем. Я перепробовал множество возможных конфигураций и не увенчался успехом. Код, который я сделал, таков:

// creates the vehicle
func createVehicle() {

    // variables for the position of the device
    guard let pointOfView = sceneView.pointOfView else { return }

    let transform = pointOfView.transform
    let orientation = SCNVector3(-transform.m31, -transform.m32, -transform.m33)
    let location = SCNVector3(transform.m41, transform.m42, transform.m43)
    let currentPositionOfCamera = orientation + location

    // vehicle scene
    let scene = SCNScene(named: "3D Models.scnassets/Placeholder.scn")

    // Main vehicle node
    let chassis = (scene?.rootNode.childNode(withName: "chassis", recursively: false))!

    // Actual Chassis node
    //let chassis2 = (scene?.rootNode.childNode(withName: "chassis2", recursively: true))!

    // vehicle wheels nodes
    let frontLeftWheel = (chassis.childNode(withName: "FLP", recursively: true))!
    let frontRightWheel = (chassis.childNode(withName: "FRP", recursively: true))!
    let rearLeftWheel = (chassis.childNode(withName: "RLP", recursively: true))!
    let rearRightWheel = (chassis.childNode(withName: "RRP", recursively: true))!

    // vehicles wheels
    let v_frontLeftWheel = SCNPhysicsVehicleWheel(node: frontLeftWheel)
    let v_frontRightWheel = SCNPhysicsVehicleWheel(node: frontRightWheel)
    let v_rearLeftWheel = SCNPhysicsVehicleWheel(node: rearLeftWheel)
    let v_rearRightWheel = SCNPhysicsVehicleWheel(node: rearRightWheel)

    // reverse wheels spin
    v_frontLeftWheel.axle = SCNVector3(-1, 0, 0)
    v_frontRightWheel.axle = SCNVector3(-1, 0, 0)
    v_rearLeftWheel.axle = SCNVector3(-1, 0, 0)
    v_rearRightWheel.axle = SCNVector3(-1, 0, 0)

    // wheels bounding boxes
    let boundingBoxFL = frontLeftWheel.boundingBox
    let boundingBoxFR = frontRightWheel.boundingBox
    let boundingBoxRL = rearLeftWheel.boundingBox
    let boundingBoxRR = rearRightWheel.boundingBox

    // center wheel location
    let centerFL:Float = 0.5 * Float(boundingBoxFL.max.x - boundingBoxFL.min.x)
    let centerFR:Float = 0.5 * Float(boundingBoxFR.max.x - boundingBoxFR.min.x)
    let centerRL:Float = 0.5 * Float(boundingBoxRL.max.x - boundingBoxRL.min.x)
    let centerRR:Float = 0.5 * Float(boundingBoxRR.max.x - boundingBoxRR.min.x)

    // connection points for the wheels
    let frontLeftWheelToChassis = frontLeftWheel.convertPosition(SCNVector3Zero, to: chassis)
    let frontLeftPositionToConnect = SCNVector3Make(frontLeftWheelToChassis.x - centerFL, frontLeftWheelToChassis.y, frontLeftWheelToChassis.z)
    v_frontLeftWheel.connectionPosition = frontLeftPositionToConnect

    let frontRightWheelToChassis = frontRightWheel.convertPosition(SCNVector3Zero, to: chassis)
    let frontRightPositionToConnect = SCNVector3Make(frontRightWheelToChassis.x + centerFR, frontRightWheelToChassis.y, frontRightWheelToChassis.z)
    v_frontRightWheel.connectionPosition = frontRightPositionToConnect

    let rearLeftWheelToChassis = rearLeftWheel.convertPosition(SCNVector3Zero, to: chassis)
    let rearLeftPositionToConnect = SCNVector3Make(rearLeftWheelToChassis.x - centerRL, rearLeftWheelToChassis.y, rearLeftWheelToChassis.z)
    v_rearLeftWheel.connectionPosition = rearLeftPositionToConnect

    let rearRightWheelToChassis = rearRightWheel.convertPosition(SCNVector3Zero, to: chassis)
    let rearRightPositionToConnect = SCNVector3Make(rearRightWheelToChassis.x + centerRR, rearRightWheelToChassis.y, rearRightWheelToChassis.z)
    v_rearRightWheel.connectionPosition = rearRightPositionToConnect

    //if the option is true, it considers all of the geometries. If false, just combines into one geometry
    let body = SCNPhysicsBody(type: .dynamic, shape: SCNPhysicsShape(node: chassis, options: [SCNPhysicsShape.Option.keepAsCompound: true]))

    // mass in kg
    body.mass = 15
    body.allowsResting = false
    body.restitution = 0.1
    body.friction = 0.1
    body.rollingFriction = 0

    // sets the position of the chassis
    chassis.position = currentPositionOfCamera

    // sets the physics body to the chassis
    chassis.physicsBody = body

    // Vehicle physics
    self.vehicle = SCNPhysicsVehicle(chassisBody: chassis.physicsBody!, wheels: [v_rearLeftWheel, v_rearRightWheel, v_frontRightWheel, v_frontLeftWheel])

    // adds the vehicle to the physics world
    self.sceneView.scene.physicsWorld.addBehavior(self.vehicle)

    // adds the vehicle to the scene
    self.sceneView.scene.rootNode.addChildNode(chassis)
}

И это моя рабочая "машина". Если колесо немного сдвинулось, проблема начинается. enter image description here

Самое близкое, что я получил колесо к 3D-модели, было это (и колеса вращались ...). На миллиметр выше, и колеса появляются в моем потолке. Я заметил, что если колеса ниже ограничительной рамки для шасси, это выглядит как на фото. Но если оно внутри, оно уходит. enter image description here

Буду очень признателен за некоторую помощь в этом, поскольку в SCNPhysicsVehicle практически нет примеров кодов, кроме того, который Apple сделал waaaaay еще в 2014 году. Даже хуже всего использовать это для AR.

...