Flyift设计模式与Swift SceneKit。对象重用

时间:2017-12-28 01:16:12

标签: swift design-patterns scenekit flyweight-pattern

我正在构建一个增强现实的iPhone应用程序,它需要渲染大量的SceneKit节点。我想整合Gamma,Helm,Johnson和Vlissides在设计模式中描述的Flyweight设计模式。还有教程Flyweight Design Pattern 但是,我遇到了实现问题以及Swift如何处理对象。

TL; DR:在Swift中有哪种方法我可以将同一SCNNode多次添加到ARSCNView并让它显示在不同的位置?

我有一个名为Box的类,用于构建SCNBox,我想利用Flyweight; Box内在状态是维度。 外在状态是它的颜色和位置。

Box Class

class Box {
    var size:CGFloat
    var position:(Float, Float, Float)
    var color:UIColor
    var node:SCNNode!

    init(color:UIColor){
        self.color = color
        /*Set the following below as default values*/
        self.size = CGFloat(0.05) //Side length
        self.position = (0,0,0)
        self.createBox()
    }

    private func createBox() -> Void {
        /*Creating box and setting its color*/
        self.node = SCNNode(geometry: SCNBox(width: size, height: size, length: size, chamferRadius: 0))
        self.node.geometry?.firstMaterial?.diffuse.contents = self.color
    }

    func draw(sceneView: ARSCNView) -> Void {
        sceneView.scene.rootNode.addChildNode(self.node)
    }
}

我有一个工厂类,它使用字典检查设计是否有相同颜色的先前对象,如果是,则重用该对象,否则创建一个新对象。

工厂类

class BoxFactory{
    var hash:[UIColor:Box] = [UIColor:Box]()
    func getBox(color c:UIColor) -> Box {
        /*Check if box of color c already exists*/
        if(self.hash[c] != nil){
            return self.hash[c]!
        }
        /*Create a new box if it does not*/
        let b:Box = Box(color: c)
        self.hash[c] = b
        return b
    }
}

一些视图控制器,它持有一个ARSCNView对象来显示这些框。

let factory:BoxFactory = BoxFactory()

/*Create two boxes of same color. One on the left and on the right*/
let leftBox:Box = factory.getBox(color: UIColor.green)
leftBox.position =  SCNVector3(-0.1,0,0)
leftBox.draw(sceneView: self.sceneView)

let rightBox:Box = factory.getBox(color: UIColor.green)
rightBox.position =  SCNVector3(0.1,0,0)
rightBox.draw(sceneView: self.sceneView)

然而,这只产生一个绿色盒子;正确的那一个。第二个getBox()调用会覆盖第一个位置图像。有没有人对这种模式的实现有什么建议,或Swift,可以帮助实现这种对象重用模式?

*旁注:我没有必要将对象的位置和颜色一起散列。因为我将拥有许多不同颜色的Box位置,它将打败重用同一个对象的整个想法。

Only one green box

1 个答案:

答案 0 :(得分:1)

SceneKit已经为您处理了这个问题。它会自动缓存几何体的网格,以便可以跨几何体有效地重复使用,并且您也可以跨几何体共享材质。如果您碰巧有重复的材质导致相同的着色器,SceneKit将只编译一次。