53131


下記のソースコード下部のLineクラスのプロパティであるlineNodeをシーンに追加した際に線色を白に指定しているにも関わらず黒く表示されてしまいます。現状どこが間違っているのか見当がつかない状況です。  
Lineクラス内のgeometryにmaterialを追加すれば反映されるはずだと思っているのですが、コードを実行した際にそうならないようです。  
下記コードはxcodeのGameテンプレートを書き換えたものです。  
swift4.2になります。

[code]

    import UIKit
    import SpriteKit
    import GameplayKit
    import SceneKit
    
    class GameViewController: UIViewController {
    
        var scene:SCNScene!
        var selectedNode:SCNNode!
    
        @IBOutlet weak var sceneView: SCNView!
        override func viewDidLoad() {
            super.viewDidLoad()
    
            if let view = self.view as! SKView? {
                // Load the SKScene from 'GameScene.sks'
                if let scene = SKScene(fileNamed: "GameScene") {
                    // Set the scale mode to scale to fit the window
                    scene.scaleMode = .aspectFill
    
                    // Present the scene
                    view.presentScene(scene)
                }
    
                view.ignoresSiblingOrder = true
    
                view.showsFPS = true
                view.showsNodeCount = true
            }
    
            //まずは基本となるSCNSceneを追加します。これが無いと始まりません
            scene = SCNScene()
    
            //SCNNodeを追加しますが、このSCNNodeに物体としてのSCNBoxを作成して関連づけます。
            let boxGeometry = SCNBox(width: 1.0, height: 1.0, length: 1.0, chamferRadius: 0.1)
            let boxNode = SCNNode(geometry: boxGeometry)
            scene.rootNode.addChildNode(boxNode)
    
            sceneView.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height)
            sceneView.center = self.view.center
            sceneView.scene = scene
            sceneView.autoenablesDefaultLighting = true;
            sceneView.allowsCameraControl = true;
    
            let cameraNode = SCNNode()
            cameraNode.camera = SCNCamera()
            cameraNode.camera?.zFar = 100
            cameraNode.camera?.zNear = 0
            scene.rootNode.addChildNode(cameraNode)
            // place the camera
            cameraNode.position = SCNVector3(x: 0, y: 0, z: 10)
    
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.objTap(_:)))
            sceneView.addGestureRecognizer(tapGesture)
    
            sceneView.backgroundColor = .gray
    
    
    
            //lineクラスのテスト
            let p1 = SCNVector3(2, 2, 0)
            let p2 = SCNVector3(-2, 2, 0)
            let p3 = SCNVector3(-2, -2, 0)
            let p4 = SCNVector3(2, -2, 0)
            let line = Line()
            line.addPoint(vector: p1)
            line.addPoint(vector: p2)
            line.addPoint(vector: p3)
            line.addPoint(vector: p4)
            line.makeGeometry()
            scene.rootNode.addChildNode(line.lineNode)
    
    
    
        }
    
    
        @objc
        func objTap(_ gestureRecognize: UIGestureRecognizer){
            let p = gestureRecognize.location(in: sceneView)
    
    
            let hitResults = sceneView.hitTest(p, options: [:])
    
            if hitResults.count > 0 {
                let result = hitResults[0]
                self.selectedNode = result.node
            }
    
    
            if self.selectedNode != nil{
    
    
                let sphereGeometry = SCNSphere(radius: 0.2)
                self.selectedNode.geometry = sphereGeometry
    
    
    
            }
    
    
    
    
    
        }
    
    
        override var shouldAutorotate: Bool {
            return true
        }
    
        override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
            if UIDevice.current.userInterfaceIdiom == .phone {
                return .allButUpsideDown
            } else {
                return .all
            }
        }
    
        override var prefersStatusBarHidden: Bool {
            return true
        }
    }
    
    
    
    class Line{
        var points: [SCNVector3] = []
        var lineNode:SCNNode = SCNNode()
        var source:SCNGeometrySource!
        var indices: [UInt32]!
        var maxPointsNum:Int = 100
    
    
        func addPoint(vector:SCNVector3){
            points.append(vector)
            if points.count > self.maxPointsNum{
                points.remove(at: 0)
            }
        }
    
        func makeGeometry(){
            source = SCNGeometrySource(vertices: points)
            indices = {var rtn = [UInt32]();for i in 0..<points.count-1{rtn += [UInt32(i), UInt32(i+1)]};return rtn}()
            let element = SCNGeometryElement(indices: indices, primitiveType: .line)
            let geometry = SCNGeometry(sources: [source], elements: [element])
            let material = SCNMaterial()
            material.diffuse.contents = UIColor.white
            geometry.materials = [material]
            lineNode.geometry = geometry
        }
    
    
    }
    
[/code]


CC BY-SA 4.0
2019-03-02T02:45:07.067
53124
2019-03-02T08:40:38.540
2019-03-02T07:25:55.640
76
25745
question
swift ios swift4
SceneKitのSCNGeometryで線を描いた時に色をつけることができない。


検索してみたところ、次のような本家英語版StackOverflowの記事が見つかりました。

[Color line in scene kit?](https://stackoverflow.com/q/28387305/6541007)

リンク先の回答には数式なんかも示されていますが、要約と若干の補足をすると、`diffuse`と言うのは「拡散反射」を指定するプロパティであり、`SceneMaterial`のデフォルトのライティングモデル(および大抵の3D描画のライティングモデル)では
**表面**
の光源に対する向きから計算した係数が`diffuse`に掛けられる(斜め向いている面を暗くする)のに対して、表面なんてものがない線分の場合、この係数が0になっちゃう、と言う意味の説明が書いてあります。

解決策としては、

  * ライティングモデルとして`SCNLightingModelConstant`を用いる
  * `diffuse`ではなく`emission`プロパティを操作する

なんてものが挙げられています。

前者をSwift 4.2の文法に合わせてあなたのコードに適用するとこうなります。

[code]

    func makeGeometry(){
        source = SCNGeometrySource(vertices: points)
        indices = {var rtn = [UInt32]();for i in 0..<points.count-1{rtn += [UInt32(i), UInt32(i+1)]};return rtn}()
        let element = SCNGeometryElement(indices: indices, primitiveType: .line)
        let geometry = SCNGeometry(sources: [source], elements: [element])
        let material = SCNMaterial()
        material.lightingModel = .constant //<-
        material.diffuse.contents = UIColor.white
        geometry.materials = [material]
        lineNode.geometry = geometry
    }
    
[/code]

後者に関しては、私が試したところではうまくいかなかったので割愛します。ご自身で試してみて、うまくいった場合には自己回答していただければと思います。


CC BY-SA 4.0
2019-03-02T08:40:38.540
53131
2019-03-02T08:40:38.540
13972
53124
answer