You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SceneKit+ARKit 实现广告牌效果时避免随相机滚转旋转的问题咨询

问题根源

你当前的实现是完全对齐相机坐标系的全视角广告牌,会同步响应相机的滚转(Roll)动作。你需要的是轴向锁定的广告牌,固定垂直方向为世界空间的全局向上方向,不受相机滚转影响。

实现逻辑

  1. 固定全局垂直向上方向为 SIMD3<Float>(0, 1, 0)(SceneKit/ARKit默认世界空间上方向)
  2. 计算从广告牌位置指向相机位置的正向向量,归一化处理
  3. 用全局上方向和正向向量叉乘得到广告牌的右方向,归一化
  4. 再用正向向量和右方向叉乘得到广告牌的修正上方向,保证垂直方向和全局上方向对齐
  5. 用最终得到的右、上向量计算四个顶点的坐标

修改后代码

// inside frame update function
struct Vertex {
    var position: SIMD3<Float>
    var texCoord: SIMD2<Float>
}
let halfSize = Float(0.25)
let cameraNode = sceneView.scene.rootNode.childNodes.first!

// 固定世界空间全局向上方向,可根据场景坐标系调整取值
let worldUp = SIMD3<Float>(0, 1, 0)
// 取广告牌和相机的世界位置
let billboardPos = self.scnNode.simdWorldTransform.position
let cameraPos = cameraNode.simdWorldTransform.position

// 计算广告牌指向相机的前方向向量
let forward = normalize(cameraPos - billboardPos)
// 推导广告牌右方向
let right = normalize(cross(worldUp, forward))
// 推导修正后的广告牌上方向,和全局上方向对齐
let up = cross(forward, right)

// 计算四个顶点的世界位置
let data = drawBuffer.contents().bindMemory(to: ParticleVertex.self, capacity: 4)
data[0].position = billboardPos + (right + up) * halfSize
data[0].texCoord = SIMD2<Float>(0, 0)

data[1].position = billboardPos + (-right + up) * halfSize
data[1].texCoord = SIMD2<Float>(1, 0)

data[2].position = billboardPos + (right - up) * halfSize
data[2].texCoord = SIMD2<Float>(0, 1)

data[3].position = billboardPos + (-right - up) * halfSize
data[3].texCoord = SIMD2<Float>(1, 1)

补充说明

如果你的场景用的不是Y轴作为垂直向上方向,修改worldUp的取值即可适配。如果需要相对广告牌父节点的局部空间垂直固定,把worldUp转换为父节点的局部空间坐标即可。


内容的提问来源于stack exchange,提问作者Matt Bierner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 07:12:05