Как правильно настроить физическое тело для размещения пользовательского поворота в SceneKitIOS

Программируем под IOS
Ответить
Anonymous
 Как правильно настроить физическое тело для размещения пользовательского поворота в SceneKit

Сообщение Anonymous »

Мне нужно установить физическое тело узла. Если у меня есть собственный поворот, но без масштабирования и вращения, я могу просто трансформировать фигуру, используя инверсию поворота, вот так:
let boxGeo = SCNBox(width: 5, height: 5, length: 1, chamferRadius: 0)
let box = SCNNode(geometry: boxGeo)
rootNode.addChildNode(box)

// i have a custom pivot here:
box.pivot = SCNMatrix4MakeTranslation(1, 1, 1)

// i can simply transform the shape by inverse of pivot:
let boxPhysicsShape = SCNPhysicsShape(geometry: box.geometry!)
.transformed(by: SCNMatrix4Invert(box.pivot))
box.physicsBody = SCNPhysicsBody(type: .static, shape: boxPhysicsShape)

Обратите внимание, что Transformed(by:) — это вспомогательная функция, которую я предоставляю ниже:

public extension SCNPhysicsShape {

func transformed(by transform: SCNMatrix4) -> SCNPhysicsShape {
return SCNPhysicsShape(
shapes: [self],
transforms: [NSValue(scnMatrix4: transform)])
}

func translated(by translation: SCNVector3) -> SCNPhysicsShape {
let transform = SCNMatrix4MakeTranslation(translation.x, translation.y, translation.z)
return transformed(by: transform)
}

func scaled(by scale: SCNVector3) -> SCNPhysicsShape {
let transform = SCNMatrix4MakeScale(scale.x, scale.y, scale.z)
return transformed(by: transform)
}

func rotated(by rotation: SCNVector4) -> SCNPhysicsShape {
let transform = SCNMatrix4MakeRotation(rotation.w, rotation.x, rotation.y, rotation.z)
return transformed(by: transform)
}

}

Это отлично работает. Однако, когда узел масштабируется, это больше не будет работать:
// ...
box.scale = SCNVector3Make(1.5, 1.5, 1.5)
box.pivot = SCNMatrix4MakeTranslation(1, 1, 1)

// ...
let boxPhysicsShape = SCNPhysicsShape(geometry: box.geometry!)
.scaled(by: box.scale)
.transformed(by: SCNMatrix4Invert(box.pivot))

Если вы включите параметр отладки showPhysicsShapes, физическая форма будет смещена.
Подобно масштабированию, когда происходит вращение, Я тоже не могу выровнять физическую форму.
Вот минимальный код воспроизведения, с которым можно поиграть:
class My3DScene: SCNScene {
override init() {
super.init()

let camera = SCNCamera()
let cameraNode = SCNNode()
cameraNode.camera = camera
cameraNode.position = SCNVector3(x: 0, y: 0, z: 50)
rootNode.addChildNode(cameraNode)

let boxGeo = SCNBox(width: 5, height: 5, length: 1, chamferRadius: 0)
boxGeo.firstMaterial?.diffuse.contents = UIColor.red
let box = SCNNode(geometry: boxGeo)
box.scale = SCNVector3Make(1.5, 1.5, 1.5)
box.eulerAngles = SCNVector3Make(1, 2, 3)
box.pivot = SCNMatrix4MakeTranslation(1, 1, 1)
rootNode.addChildNode(box)

let boxPhysicsShape = SCNPhysicsShape(geometry: box.geometry!)
// no need to rotate, shape is rotated by node automatically
.scaled(by: box.scale)
.transformed(by: SCNMatrix4Invert(box.pivot))
box.physicsBody = SCNPhysicsBody(type: .static, shape: boxPhysicsShape)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

class GameViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

let scnView = SCNView(frame: self.view.frame)
scnView.debugOptions = .showPhysicsShapes

self.view.addSubview(scnView)
let scene = My3DScene()
scnView.present(scene, with: .fade(withDuration: 1), incomingPointOfView: nil)
}
}

public extension SCNPhysicsShape {

func transformed(by transform: SCNMatrix4) -> SCNPhysicsShape {
return SCNPhysicsShape(
shapes: [self],
transforms: [NSValue(scnMatrix4: transform)])
}

func translated(by translation: SCNVector3) -> SCNPhysicsShape {
let transform = SCNMatrix4MakeTranslation(translation.x, translation.y, translation.z)
return transformed(by: transform)
}

func scaled(by scale: SCNVector3) -> SCNPhysicsShape {
let transform = SCNMatrix4MakeScale(scale.x, scale.y, scale.z)
return transformed(by: transform)
}

func rotated(by rotation: SCNVector4) -> SCNPhysicsShape {
let transform = SCNMatrix4MakeRotation(rotation.w, rotation.x, rotation.y, rotation.z)
return transformed(by: transform)
}

}


Подробнее здесь: https://stackoverflow.com/questions/792 ... n-scenekit
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»