问题
I am looking for a way to set the pivot of SCNNodes (obtained from importing Collada files) to their centroid (or the center of their bounding box. I get the center with
SCNVector3 center;
CGFloat radius;
[node getBoundingSphereCenter:¢er radius:&radius];
However, when I try to set the node's pivot (which is a 4D vector as opposed to the 3D vector of the center) to the center, the node's position also changes.
node.pivot = SCNMatrix4MakeTranslation(center.x,center.y,center.z);
How can I offset this movement - resp. how can I only change the node's pivot without affecting its position in space? Or is there even a way (without using additional empty nodes) to do it in Interface Builder?
回答1:
The pivot is not only the center of rotation, it is the node's reference point for position. When you reset the pivot, the position of the pivot relative to the parent object remains fixed. You are, in effect, moving the geometry relative to the object's current position.
The simple fix is to reposition the node using the negative values of those used to reset the pivot. If, for some reason, you need a specific value that doesn't allow this, put your node in a container node and use the container node for position and your re-pivoted node for rotation.
回答2:
The same question was also asked here Is it normal for an SCNNode pivot to change the nodes position? ... but after searching online for hours I couldn't find any coded solution to this problem. Which is how does one center the pivot of a node without moving the node.
So in the end I spend most of today working on this coded answer below. What I found was that the orientation of the local axis determines whether you subtract or do an addition for the correction factor.
Take this bike below. The right-hand pedal crank pivot z-axis (blue) is pointing upwards, whilst in the other photo, left-hand pedal crank pivot z-axis (blue) is pointing downwards. That reason these axis is different is when the person was drawing the bike model in SketchUp, they just copied and flipped the first pedal crank to the opposite side. So unfortunately, its very common to get imported DAE models with ad-hoc pivot orientation and positions!
func centerPivotWithOutMoving(for node: SCNNode) -> SCNNode {
let initialPos = activeNode.presentation.position
var min = SCNVector3Zero
var max = SCNVector3Zero
node.__getBoundingBoxMin(&min, max: &max)
node.pivot = SCNMatrix4MakeTranslation(
min.x + (max.x - min.x)/2,
min.y + (max.y - min.y)/2,
min.z + (max.z - min.z)/2
)
let correctX = Float(min.x + (max.x - min.x)/2)
let correctY = Float(min.y + (max.y - min.y)/2)
let correctZ = Float(min.z + (max.z - min.z)/2)
if node.convertVector(SCNVector3(0,0,1), from: parentNode).z < 0 {
// if blue local z-axis is pointing downwards
node.position = SCNVector3(initialPos.x - correctX, initialPos.y - correctY, initialPos.z - correctZ)
} else {
// if blue local z-axis is pointing upwards
node.position = SCNVector3(initialPos.x + correctX, initialPos.y + correctY, initialPos.z + correctZ)
}
return node
}
I've only tested the code above on the two different z-axis orientations shown above, the complete code would also have to deal with x, y axis using these two conditions.
node.convertVector(SCNVector3(0,1,0), from: parentNode).z < 0
node.convertVector(SCNVector3(1,0,0), from: parentNode).z < 0
If there is a better way to do this... please share?
来源:https://stackoverflow.com/questions/38391292/set-pivot-of-scnnode-to-bounding-volume-center-without-changing-the-nodes-posit