-1.3 C
New York
Wednesday, January 15, 2025

ios – The right way to set physics physique appropriately to accommodate customized pivot in SceneKit


I have to set the physics physique of a node. When I’ve a customized pivot however with out scales or rotation, I can merely remodel the form by the inverse of the pivot, like this:

    let boxGeo = SCNBox(width: 5, peak: 5, size: 1, chamferRadius: 0)
    let field = SCNNode(geometry: boxGeo)
    rootNode.addChildNode(field)

    // i've a customized pivot right here: 
    field.pivot = SCNMatrix4MakeTranslation(1, 1, 1)
    
    // i can merely remodel the form by inverse of pivot:
    let boxPhysicsShape = SCNPhysicsShape(geometry: field.geometry!)
      .reworked(by: SCNMatrix4Invert(field.pivot))
    field.physicsBody = SCNPhysicsBody(kind: .static, form: boxPhysicsShape)

Notice that reworked(by:) is a helper operate that I present beneath:


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

  func translated(by translation: SCNVector3) -> SCNPhysicsShape {
    let remodel = SCNMatrix4MakeTranslation(translation.x, translation.y, translation.z)
    return reworked(by: remodel)
  }
  
  func scaled(by scale: SCNVector3) -> SCNPhysicsShape {
    let remodel = SCNMatrix4MakeScale(scale.x, scale.y, scale.z)
    return reworked(by: remodel)
  }
  
  func rotated(by rotation: SCNVector4) -> SCNPhysicsShape {
    let remodel = SCNMatrix4MakeRotation(rotation.w, rotation.x, rotation.y, rotation.z)
    return reworked(by: remodel)
  }
  
}

This works positive. Nevertheless, when the node is scaled, this would possibly not work anymore:

    // ...
    field.scale = SCNVector3Make(1.5, 1.5, 1.5)
    field.pivot = SCNMatrix4MakeTranslation(1, 1, 1)

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

In the event you activate the showPhysicsShapes debug possibility, the physics form is misaligned.

Much like scale, when there’s rotation concerned, I can not align the physics form both.

Here is a minimal repro code you may mess around:

class My3DScene: SCNScene {
  override init() {
    tremendous.init()
    
    let digital camera = SCNCamera()
    let cameraNode = SCNNode()
    cameraNode.digital camera = digital camera
    cameraNode.place = SCNVector3(x: 0, y: 0, z: 50)
    rootNode.addChildNode(cameraNode)
    
    let boxGeo = SCNBox(width: 5, peak: 5, size: 1, chamferRadius: 0)
    boxGeo.firstMaterial?.diffuse.contents = UIColor.crimson
    let field = SCNNode(geometry: boxGeo)
    field.scale = SCNVector3Make(1.5, 1.5, 1.5)
    field.eulerAngles = SCNVector3Make(1, 2, 3)
    field.pivot = SCNMatrix4MakeTranslation(1, 1, 1)
    rootNode.addChildNode(field)
    
    let boxPhysicsShape = SCNPhysicsShape(geometry: field.geometry!)
      // no have to rotate, form is rotated by node robotically
      .scaled(by: field.scale)
      .reworked(by: SCNMatrix4Invert(field.pivot))
    field.physicsBody = SCNPhysicsBody(kind: .static, form: boxPhysicsShape)
  }
  
  required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been carried out")
  }
}


class GameViewController: UIViewController {

    override func viewDidLoad() {
        tremendous.viewDidLoad()
        
      
      let scnView = SCNView(body: self.view.body)
      scnView.debugOptions = .showPhysicsShapes
      
      self.view.addSubview(scnView)
      let scene = My3DScene()
      scnView.current(scene, with: .fade(withDuration: 1), incomingPointOfView: nil)
   }
}


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

  func translated(by translation: SCNVector3) -> SCNPhysicsShape {
    let remodel = SCNMatrix4MakeTranslation(translation.x, translation.y, translation.z)
    return reworked(by: remodel)
  }
  
  func scaled(by scale: SCNVector3) -> SCNPhysicsShape {
    let remodel = SCNMatrix4MakeScale(scale.x, scale.y, scale.z)
    return reworked(by: remodel)
  }
  
  func rotated(by rotation: SCNVector4) -> SCNPhysicsShape {
    let remodel = SCNMatrix4MakeRotation(rotation.w, rotation.x, rotation.y, rotation.z)
    return reworked(by: remodel)
  }
  
}

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles