iOS ARKit旋转3D物体异常求助:旋转中心偏移及移动后角度问题
Hey Jack, let's tackle those two frustrating issues you're dealing with—they're classic pitfalls when working with ARKit/SceneKit, so we'll get you sorted out quickly.
1. Rotating Around the Top-Left Corner Instead of Center
The root cause here is almost always the pivot point of your SCNNode being set to its default position (usually the model's origin, which might be the top-left corner if your 3D asset wasn't exported with a centered origin). Here's how to fix it:
First, calculate the center of your node's bounding box and set that as the pivot. This ensures rotation happens around the object's actual center:
func centerNodePivot(_ node: SCNNode) { let boundingBox = node.boundingBox let centerX = (boundingBox.max.x - boundingBox.min.x) / 2 + boundingBox.min.x let centerY = (boundingBox.max.y - boundingBox.min.y) / 2 + boundingBox.min.y let centerZ = (boundingBox.max.z - boundingBox.min.z) / 2 + boundingBox.min.z node.pivot = SCNMatrix4MakeTranslation(centerX, centerY, centerZ) }
Call this function right after you load your 3D model (e.g., when adding it to the AR scene). If you're using a USDZ asset, you can also fix the origin in your 3D modeling tool (like Blender or Maya) before exporting—this avoids needing extra code.
Another thing to check: if you're attaching the node to an ARAnchor, make sure the node's position relative to the anchor is centered, not offset to the corner.
2. Abnormal Movement After ~30 Degrees of Rotation
This is almost certainly a coordinate space mismatch. When you rotate the node, its local coordinate system (the x/y/z axes relative to the object itself) no longer aligns with the world coordinate system. If your movement logic uses world coordinates, the object will move in the wrong direction.
Here's how to fix your pan gesture handling to use the node's local space:
@objc func handlePanGesture(_ gesture: UIPanGestureRecognizer) { guard let selectedNode = yourSelectedARNode else { return } let translation = gesture.translation(in: arView) // Adjust the multiplier (0.01) to control movement speed let localMoveVector = SCNVector3(translation.x * 0.01, -translation.y * 0.01, 0) // Update position using local coordinates instead of world coordinates selectedNode.localPosition += localMoveVector gesture.setTranslation(.zero, in: arView) }
By using localPosition instead of position, you're telling the node to move along its own rotated axes, not the fixed world axes. If you need to move along a specific axis relative to the camera, you might need to convert the gesture translation to the camera's coordinate space first, but for object-local movement, localPosition is the way to go.
Also, double-check that your gesture recognizers aren't accidentally resetting the node's rotation or position when the gesture state changes (e.g., ending the pan gesture).
内容的提问来源于stack exchange,提问作者Jack

