2016-01-26 3 views
3

Я хотел бы иметь возможность добавлять фигуры на поверхность сферы с помощью SceneKit. Я начал с простого примера, когда я просто пытаюсь покрасить часть поверхности сферы другим цветом. Я хотел бы, чтобы это был объект, который можно использовать, выбран и т. Д., Поэтому я думал о добавлении фигур как SCNNodes с использованием пользовательских объектов SCNShape для геометрии.Добавить фигуру на поверхность сферы в SceneKit

У меня теперь синий квадрат, который я рисую из серии очков и добавляю к сцене, содержащей красную сферу. Это в основном заканчивается касательной к точке на сфере, но реальная цель - нарисовать ее на поверхности. Есть ли что-нибудь в 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) 

ответ

6

Если вы хотите отображать 2D-контент на поверхность объекта 3D SceneKit и иметь динамический/интерактивный 2D-контент, одним из самых простых решений является использование SpriteKit для 2D-контента. Вы можете настроить диффузное содержимое вашей сферы на SKScene и создать/разместить/украсить узлы SpriteKit в этой сцене, чтобы расположить их на лицевой стороне сферы.

Если вы хотите, чтобы этот контент отвечал на события нажатия ... Используя hitTest в вашем представлении SceneKit, вы получите SCNHitTestResult, и из этого вы можете получить координаты текстуры для точки попадания на сферу. Из текстурных координат вы можете конвертировать в SKScene координаты и создавать узлы, запускать действия или что угодно.

Для получения более подробной информации, ваш лучший вариант, вероятно, представляет собой проект кода Apple SceneKitReel. Это демонстрация, которая представила SceneKit для iOS на WWDC14. В этой демонстрации есть «слайд», где красящие глобусы летают с камеры на вращающемся торе и оставляют брызги краски там, где они попали - тора имеет сцену SpriteKit в качестве материала, а трюк для оставления брызг при столкновениях в основном такой же hit test -> координата текстуры -> координированный подход SpriteKit, описанный выше.

+0

Просматривая ящик с наборами яблок с их исходным кодом, я вижу, что они фактически используют диффузный контент как «SKScene», но я не могу его воссоздать. Есть ли у вас какие-либо идеи относительно того, как вы собираетесь устанавливать диффузное содержимое в виде skscene? –

3

SceneKit книга Дэвида Ronnqvist имеет пример (EarthView пример, говорящий глобус, глава 5), что стоит посмотреть. В этом примере создается трехугольная кнопка, которая затем прикрепляется к поверхности земного шара в месте расположения крана.

Ваша проблема сложнее, потому что вы строите фигуру, покрывающую сегмент сферы. Ваш «квадрат» - это действительно сферическая трапеция, сегмент сферы, ограниченный четырьмя большими дугами окружности. Я вижу три возможных подхода, в зависимости от того, что вы в конечном счете ищете.

Простейший способ сделать это - использовать изображение в качестве материала для поверхности сферы. Этот подход хорошо иллюстрируется примером Ronnqvist EarthView, который использует несколько изображений для отображения земной поверхности. Вместо того, чтобы рисовать континенты, вы нарисуете свой квадрат. Однако этот подход не подходит для интерактивности. Посмотрите на SCNMaterial.

Другим подходом было бы использование результатов испытаний на результат. Это зафиксировано на SCNSceneRenderer (что соответствует SCNView) и SCNHitTest. Используя результаты теста попадания, вы можете вытащить лицо, которое было постукивано, а затем его элементы геометрии. Это не приведет вас домой, потому что SceneKit использует треугольники для SCNSphere, и вы ищете квадроциклы. Вы также ограничены квадратами, которые выстраиваются в линию с помощью каркасного представления SceneKit.

Если вам нужен полный контроль над тем, где нарисован «квадрат», включая изменение его угла относительно экватора, я думаю, вам придется строить свою собственную геометрию с нуля. Это означает вычисление широты/долготы каждой угловой точки, затем формирование дуг между этими точками, а затем вычисление связки промежуточных точек вдоль дуг. Вам нужно будет добавить фактор выдумки, чтобы поднять промежуточные точки чуть выше поверхности сферы и создать свои собственные квадроциклы или треугольные полосы. Занятия здесь: SCNGeometry, SCNGeometryElement и SCNGeometrySource.

+0

Здесь есть несколько хороших моментов, но для того, чтобы отметить области на поверхности сферы, подобный геометрический подход, как это, может быть более сложным, чем это стоит. Для некоторых эффектов, по крайней мере, проще работать с точки зрения текстурной карты сферы (см. [Мой ответ] (http://stackoverflow.com/a/35029597/957768)). Опять же, если вы хотите делать «3D-вещи» с этими регионами (скажем, имея страны, снимающие Землю и улетающие), пользовательская геометрия будет единственным способом. – rickster

+0

Оцените ответ, Hal. У меня есть чтение. – jday

Смежные вопросы