如何根据枢轴调整节点
How to adjust node as per pivot
场景包中
假设
我有 2 个 BOX,带 PIVOT 的 box1,不带 PIVOT
的 box2
我的目标是通过转换匹配两个框
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)
方框 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"
现在我缩放 BOX1 和 box2
planeNode.scale.y = 4
planeNode2.scale.y = 4
因为 planeNode
有枢轴所以它将从底部开始缩放,但是 Plane2 将从中心开始缩放
我如何计算 plane2 的位置以匹配 plane1
你的两个盒子都有支点。默认情况下,对于 SCNBox,它位于对象中心(边界框的中心)。您所做的是移动第一个 Box 的 Pivot。场景对象将始终相对于其当前枢轴位置放置。所以当你向上移动Y轴的枢轴时,物体将处于较低的位置。
当您将第二个对象设置为与第一个对象相同的位置时,您可以匹配两个对象的位置,然后将第一个对象的枢轴的反向偏移添加到第二个对象的位置。
制作这样的东西:
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
}
您还需要这个数学扩展:
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
}
}
场景包中
假设 我有 2 个 BOX,带 PIVOT 的 box1,不带 PIVOT
的 box2我的目标是通过转换匹配两个框
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)
方框 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"
现在我缩放 BOX1 和 box2
planeNode.scale.y = 4
planeNode2.scale.y = 4
因为 planeNode
有枢轴所以它将从底部开始缩放,但是 Plane2 将从中心开始缩放
我如何计算 plane2 的位置以匹配 plane1
你的两个盒子都有支点。默认情况下,对于 SCNBox,它位于对象中心(边界框的中心)。您所做的是移动第一个 Box 的 Pivot。场景对象将始终相对于其当前枢轴位置放置。所以当你向上移动Y轴的枢轴时,物体将处于较低的位置。
当您将第二个对象设置为与第一个对象相同的位置时,您可以匹配两个对象的位置,然后将第一个对象的枢轴的反向偏移添加到第二个对象的位置。
制作这样的东西:
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
}
您还需要这个数学扩展:
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
}
}