Я делаю 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)
}
И это моя рабочая "машина". Если колесо немного сдвинулось, проблема начинается.
Самое близкое, что я получил колесо к 3D-модели, было это (и колеса вращались ...). На миллиметр выше, и колеса появляются в моем потолке. Я заметил, что если колеса ниже ограничительной рамки для шасси, это выглядит как на фото. Но если оно внутри, оно уходит.
Буду очень признателен за некоторую помощь в этом, поскольку в SCNPhysicsVehicle практически нет примеров кодов, кроме того, который Apple сделал waaaaay еще в 2014 году. Даже хуже всего использовать это для AR.