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

ARKit 3D空间中UIBezierPath创建平面图形异常问题排查

Fixing UIBezierPath & SCNShape Misalignment in ARKit App

Hey there, let's figure out why your ARKit app is having shape distortion and position issues when creating a second wall or rotating the device. The core problem here is incorrect coordinate space handling—you're mixing 3D world coordinates with 2D path coordinates without proper conversion. Let's break down the fixes step by step:

1. The Root Cause

When you create UIBezierPath for SCNShape, the path uses local coordinate space relative to the node it's attached to (your windowNode). But right now, you're using worldCoordinates directly, which are global to the AR scene. When you rotate the device or create a new windowNode with a different transform, these world coordinates don't map correctly to the local space of the new wall, causing the shape to warp or shift.

2. Step-by-Step Fixes

A. Convert World Coordinates to Window Node's Local Space

Instead of using raw world coordinates for your path points, convert them to the local space of the windowNode you're drawing on. This ensures your path points are relative to the wall's position and orientation.

Replace your point conversion code with this:

if firstHit.node == windowNode {
    // Convert world hit position to windowNode's local coordinate space
    let localHitPosition = windowNode.convertPosition(firstHit.worldCoordinates, from: nil)
    // Map 3D local position to 2D CGPoint (use X and Y since we're drawing on the SCNPlane)
    let pointCoordinates = CGPoint(x: CGFloat(localHitPosition.x), y: CGFloat(localHitPosition.y))
    
    // Rest of your sphere creation code stays the same...
    let sphere = SCNSphere(radius: 0.02)
    sphere.firstMaterial?.diffuse.contents = UIColor.white
    sphere.firstMaterial?.lightingModel = .constant
    let sphereNode = SCNNode(geometry: sphere)
    sceneView.scene.rootNode.addChildNode(sphereNode)
    sphereNode.worldPosition = firstHit.worldCoordinates
    
    if points.isEmpty {
        windowPath.move(to: pointCoordinates)
    } else {
        windowPath.addLine(to: pointCoordinates)
    }
    points.append(sphereNode)
    if undoButton.alpha == 0 {
        undoButton.alpha = 1
    }
}

B. Attach the Shape Node to the Window Node

When creating your final SCNShape node, add it as a child of windowNode instead of setting its world position directly. This inherits the wall's transform, so the shape stays aligned even if the wall is rotated or moved relative to the world.

Modify the shape creation code:

else if firstHit.node == points.first {
    windowPath.close()
    // Use a tiny extrusion depth (0 might cause rendering issues)
    let windowShape = SCNShape(path: windowPath, extrusionDepth: 0.001)
    windowShape.firstMaterial?.diffuse.contents = UIColor.white
    windowShape.firstMaterial?.lightingModel = .constant
    let tintedWindow = SCNNode(geometry: windowShape)
    
    // Add as child of windowNode instead of setting worldPosition
    windowNode.addChildNode(tintedWindow)
    // Set local position to (0,0,0) since the path is already relative to windowNode's space
    tintedWindow.position = SCNVector3Zero
    
    // Cleanup: Remove spheres and reset path for next use
    points.forEach { $0.removeFromParentNode() }
    points.removeAll()
    windowPath.removeAllPoints()
}

C. Reset Path and Points for New Walls

Make sure you reset your windowPath and points array every time you create a new transparent wall. This prevents leftover points from the previous wall messing up the new shape:

Add these lines when creating a new windowNode:

// After initializing windowNode...
sceneView.scene.rootNode.addChildNode(windowNode)
windowNode.simdTransform = currentFrame.camera.transform
windowNode.opacity = 0.1

// Reset path and points for the new wall
windowPath = UIBezierPath()
points.removeAll()

3. Why This Works

  • Local Coordinate Conversion: By converting hit positions to windowNode's local space, your UIBezierPath points are always relative to the wall's surface, regardless of the device's orientation or the wall's position in the world.
  • Child Node Attachment: Adding the shape as a child of windowNode ensures it inherits all the wall's transformations (rotation, position, scale), so it stays perfectly aligned with the wall at all times.
  • Clean State for New Walls: Resetting the path and points ensures each wall's shape starts fresh, no cross-contamination from previous sessions.

Give these changes a try—your shapes should stay aligned correctly even when rotating the device or creating multiple walls!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:19:21