簡體   English   中英

在SceneKit中向球體表面添加形狀

[英]Add shape to sphere surface in SceneKit

我希望能夠使用SceneKit向球體表面添加形狀。 我從一個簡單的例子開始,我只是試圖為球體表面的一部分着色另一種顏色。 我希望這是一個可以被點擊,選擇等的對象...所以我的想法是使用自定義SCNShape對象為幾何體添加形狀作為SCNNodes

我現在擁有的是一個藍色正方形,我從一系列點中繪制並添加到包含紅色球體的場景中。 它基本上與球體上的一個點相切,但真正的目標是在表面上繪制它。 SceneKit中有什么東西可以讓我這樣做嗎? 我是否需要進行一些數學/幾何以使其與球體形狀相同或映射到球體的坐標? 我正在嘗試在SceneKit的范圍之外做什么?

如果這個問題過於寬泛,我會很高興有人能指出我的書或資源來了解我所缺少的東西。 我對SceneKit和3D一般都很陌生,只是玩得很​​開心。

這是我現在擁有的游樂場代碼:

import UIKit
import SceneKit
import XCPlayground

class SceneViewController: UIViewController {

    let sceneView = SCNView()

    private lazy var sphere: SCNSphere = {
        let sphere = SCNSphere(radius: 100.0)
        sphere.materials = [self.surfaceMaterial]
        return sphere
    }()

    private lazy var testScene: SCNScene = {
        let scene = SCNScene()
        let sphereNode: SCNNode = SCNNode(geometry: self.sphere)
        sphereNode.addChildNode(self.blueChildNode)

        scene.rootNode.addChildNode(sphereNode)
        //scene.rootNode.addChildNode(self.blueChildNode)
        return scene
    }()

    private lazy var surfaceMaterial: SCNMaterial = {
        let material = SCNMaterial()
        material.diffuse.contents = UIColor.redColor()
        material.specular.contents = UIColor(white: 0.6, alpha: 1.0)
        material.shininess = 0.3
        return material
    }()

    private lazy var blueChildNode: SCNNode = {
        let node: SCNNode = SCNNode(geometry: self.blueGeometry)
        node.position = SCNVector3(0, 0, 100)
        return node
    }()

    private lazy var blueGeometry: SCNShape = {
        let points: [CGPoint] = [
            CGPointMake(0, 0),
            CGPointMake(50, 0),
            CGPointMake(50, 50),
            CGPointMake(0, 50),
            CGPointMake(0, 0)]

        var pathRef: CGMutablePathRef = CGPathCreateMutable()
        CGPathAddLines(pathRef, nil, points, points.count)

        let bezierPath: UIBezierPath = UIBezierPath(CGPath: pathRef)
        let shape = SCNShape(path: bezierPath, extrusionDepth: 1)
        shape.materials = [self.blueNodeMaterial]
        return shape
    }()

    private lazy var blueNodeMaterial: SCNMaterial = {
        let material = SCNMaterial()
        material.diffuse.contents = UIColor.blueColor()
        return material
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        sceneView.frame = self.view.bounds
        sceneView.backgroundColor = UIColor.blackColor()
        self.view.addSubview(sceneView)

        sceneView.autoenablesDefaultLighting = true
        sceneView.allowsCameraControl = true

        sceneView.scene = testScene
    }
}

XCPShowView("SceneKit", view: SceneViewController().view)

如果要將2D內容映射到3D SceneKit對象的表面,並使2D內容成為動態/交互式,最簡單的解決方案之一是將SpriteKit用於2D內容。 您可以將球體的漫反射內容設置為SKScene ,並在該場景中創建/定位/修飾SpriteKit節點,以將它們排列在球體的面上。

如果你想讓這個內容響應點擊事件...在SceneKit視圖中使用hitTest會獲得一個SCNHitTestResult ,從中你可以得到球體上命中點的紋理坐標。 從紋理坐標,您可以轉換為SKScene坐標並生成節點,運行操作或其他任何內容。

有關更多詳細信息,您最好的選擇可能是Apple的SceneKitReel示例代碼項目。 這是在WWDC14上為iOS引入SceneKit的演示。 在那個演示中有一個“幻燈片”,其中油漆球在旋轉的圓環上從相機飛出並留下油漆濺到它們的位置 - 圓環有一個SpriteKit場景作為其材料,並且在碰撞時留下飛濺的技巧基本相同命中測試 - >紋理坐標 - >上面概述的SpriteKit坐標方法。

DavidRönnqvist的SceneKit書(作為iBook提供)有一個值得關注的例子( EarthView示例 ,一個說話的地球,第5章)。 該示例構造3D圖釘,然后將其附接到龍頭位置處的地球表面。

你的問題更復雜,因為你正在構建一個覆蓋球體一部分的形狀。 你的“方形”實際上是一個球形梯形,是由四個大圓弧界定的球體的一部分。 我可以看到三種可能的方法,具體取決於您最終要尋找的內容。

最簡單的方法是使用圖像作為球體表面的材料。 在Ronnqvist EarthView示例中很好地說明了這種方法,該示例使用多個圖像來顯示地球表面。 你不是畫大陸,而是畫你的廣場。 但是,這種方法不適合交互性。 看看SCNMaterial

另一種方法是使用命中測試結果。 這是在SCNSceneRendererSCNView符合)和SCNHitTest 使用命中測試結果,您可以拉出被輕擊的面,然后拉出其幾何元素。 但是,這不會讓你一直回家,因為SceneKit使用三角形SCNSphere ,你正在尋找四邊形。 您還將被限制為與SceneKit的底層線框表示對齊的正方形。

如果你想完全控制繪制“方形”的位置,包括改變它相對於赤道的角度,我認為你必須從頭開始構建自己的幾何體。 這意味着計算每個角點的緯度/經度,然后在這些點之間生成弧,然后計算沿弧的一堆中間點。 你必須添加一個軟糖因子,將中間點提升到略高於球體表面的位置,然后建立自己的四邊形或三角形條帶。 這里的類是SCNGeometrySCNGeometryElementSCNGeometrySource

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM