In Scenekit
let's say I have 2 BOX , box1 with PIVOT , box2 without PIVOT
My Goal is to match both of boxes with transformation
let plane = SCNBox(width: 12, height: 2, length: 12, chamferRadius: 0)
plane.firstMaterial?.diffuse.contents = UIColor.red
let planeNode = SCNNode(geometry: plane)
planeNode.name = "Plane1"
planeNode.pivot = SCNMatrix4MakeTranslation(0, -0.5, 0)
Box 2
let plane2 = SCNBox(width: 12, height: 2, length: 12, chamferRadius: 0)
plane2.firstMaterial?.diffuse.contents = UIColor.red
let planeNode2 = SCNNode(geometry: plane2)
planeNode2.name = "Plane2"
Now I scale BOX1 and box2
planeNode.scale.y = 4
planeNode2.scale.y = 4
as planeNode
has pivot so it will be scale from bottom , but Plane2 will be scale from center
How can I calculate position of plane2 that it will match the plane1
Both of your boxes have pivots. By default, for SCNBox, it's in the objects center (the center of the Bounding Box). What you do is shifting the Pivot of your first Box. The Scene Object will always be placed relative to its current pivot position. So when you move up the pivot of the Y axis, the object will be in a lower position.
You can match both object positions when you set the second object to the same position as the first object, then you add the inverted offset of the pivot from the first object to the position of the second object.
make something like this:
func alignPosition() {
// Calculate offset position
let offset = SCNVector3(planeNode.pivot.m41, planeNode.pivot.m42, planeNode.pivot.m43)
// Set the seconds node to the position as the first node
// without changing it's pivot, then subtract the offset
planeNode2.position = planeNode.position - offset
}
you will also need this math extensions:
extension CGPoint {
init(_ size: CGSize) {
self.init()
self.x = size.width
self.y = size.height
}
init(_ vector: SCNVector3) {
self.init()
self.x = CGFloat(vector.x)
self.y = CGFloat(vector.y)
}
func distanceTo(_ point: CGPoint) -> CGFloat {
return (self - point).length()
}
func length() -> CGFloat {
return sqrt(self.x * self.x + self.y * self.y)
}
func midpoint(_ point: CGPoint) -> CGPoint {
return (self + point) / 2
}
static func + (left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x + right.x, y: left.y + right.y)
}
static func - (left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x - right.x, y: left.y - right.y)
}
static func += (left: inout CGPoint, right: CGPoint) {
left = left + right
}
static func -= (left: inout CGPoint, right: CGPoint) {
left = left - right
}
static func / (left: CGPoint, right: CGFloat) -> CGPoint {
return CGPoint(x: left.x / right, y: left.y / right)
}
static func * (left: CGPoint, right: CGFloat) -> CGPoint {
return CGPoint(x: left.x * right, y: left.y * right)
}
static func /= (left: inout CGPoint, right: CGFloat) {
left = left / right
}
static func *= (left: inout CGPoint, right: CGFloat) {
left = left * right
}
}
extension SCNVector3
{
static func + (left: SCNVector3, right: SCNVector3) -> SCNVector3 {
return SCNVector3Make(left.x + right.x, left.y + right.y, left.z + right.z)
}
static func - (left: SCNVector3, right: SCNVector3) -> SCNVector3 {
return SCNVector3Make(left.x - right.x, left.y - right.y, left.z - right.z)
}
static func * (vector: SCNVector3, scalar: Float) -> SCNVector3 {
return SCNVector3Make(vector.x * scalar, vector.y * scalar, vector.z * scalar)
}
static func / (vector: SCNVector3, scalar: Float) -> SCNVector3 {
if scalar == 0.0 { return SCNVector3() }
return SCNVector3Make(vector.x / scalar, vector.y / scalar, vector.z / scalar)
}
func lengthSquared() -> Float {
return x*x + y*y + z*z
}
func length() -> Float {
return sqrtf(lengthSquared())
}
func normalize() -> SCNVector3 {
let len:Float = 1.0 / sqrt(lengthSquared())
return self * len
}
func distanceFrom(_ v: SCNVector3) -> Float {
let dx = x - v.x
let dy = y - v.y
let dz = z - v.z
return sqrt(dx*dx + dy*dy + dz*dz)
}
func minus(_ other:SCNVector3) -> SCNVector3 { return SCNVector3(x - other.x, y - other.y, z - other.z) }
func normalized() -> SCNVector3 {
let len = length()
var ans = SCNVector3()
ans.x = self.x / len
ans.y = self.y / len
ans.z = self.z / len
return ans
}
}