Легкая конструкция с использованием Swift SceneKit. Объект повторного использования

Я создаю приложение для iPhone с дополненной реальностью, и для его визуализации потребуется большое количество узлов SceneKit. Я хочу интегрировать шаблон проектирования Flyweight, описанный в " Шаблонах проектирования " Гаммой, Хелмом, Джонсоном и Влиссидесом. Также здесь есть учебник Flyweight Design Pattern. Однако у меня возникают проблемы с реализацией и с тем, как Swift обрабатывает объекты.

TL; DR: есть ли способ в Swift, где я могу добавить то же самое SCNNode к ARSCNView более одного раза и будет ли он отображаться в разных позициях?

У меня есть класс под названием Box который строит SCNBoxна которых я хочу использовать Flyweight; внутреннее состояние Box это размеры. Внешнее состояние - это его цвет и положение.

Класс Box

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() call переопределяет первую позицию. Изображение ниже. Есть ли у кого-нибудь совет по реализации этого шаблона или Swift, который может помочь в достижении этого шаблона повторного использования объекта?

* Примечание: мне не нужно хешировать положение объекта вместе с его цветом. Будучи, что у меня будет много BoxЕсли они различаются по цвету и положению, это уничтожит саму идею повторного использования одного и того же объекта.

Только одна зеленая коробка

1 ответ

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

Другие вопросы по тегам