import SwiftUI import SceneKit // MARK: - Custom Colors extension UIColor { static let placeholderBackground = UIColor(red: 0.2, green: 0.5, blue: 0.8, alpha: 1.0) static let placeholderDisabledBackground = UIColor.gray static let placeholderFilteredOutBackground = UIColor.lightGray static let placeholderIcon = UIColor.white static let placeholderDisabledIcon = UIColor.white } // MARK: - Main View struct ContentView: View { @State private var gridSize: Double = 5 @State private var scene: SCNScene? private var optimizedGridManager: OptimizedGridManager = OptimizedGridManager() var body: some View { ZStack { SceneView( scene: scene ?? createScene(), pointOfView: createCamera(), options: [.allowsCameraControl, .autoenablesDefaultLighting] ) .edgesIgnoringSafeArea(.all) .onChange(of: gridSize) { _, _ in // Debounce scene recreation DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { scene = createScene() } } VStack { Spacer() // Grid size slider VStack { Text("Grid Size: \(Int(gridSize)) x \(Int(gridSize))") .foregroundColor(.white) .padding(.bottom, 5) Slider(value: $gridSize, in: 1...150, step: 1) .padding(.horizontal) } .padding() .background(Color.black.opacity(0.7)) .cornerRadius(10) .padding() } } } private func createScene() -> SCNScene { let scene = SCNScene() // Add ambient light let ambientLight = SCNNode() ambientLight.light = SCNLight() ambientLight.light?.type = .ambient ambientLight.light?.intensity = 100 scene.rootNode.addChildNode(ambientLight) // Add directional light let directionalLight = SCNNode() directionalLight.light = SCNLight() directionalLight.light?.type = .directional directionalLight.light?.intensity = 1000 directionalLight.position = SCNVector3(x: 0, y: 10, z: 10) directionalLight.eulerAngles = SCNVector3(x: -Float.pi/4, y: 0, z: 0) scene.rootNode.addChildNode(directionalLight) // Create grid of nodes optimizedGridManager.createGrid(size: Int(gridSize), in: scene) return scene } private func createCamera() -> SCNNode { let cameraNode = SCNNode() cameraNode.camera = SCNCamera() cameraNode.position = SCNVector3(x: 0, y: 5, z: 10) cameraNode.eulerAngles = SCNVector3(x: -Float.pi/6, y: 0, z: 0) return cameraNode } } class OptimizedGridManager { private let geometryPool: GeometryPool private var gridNode: SCNNode? init() { // Create shared geometry instances self.geometryPool = GeometryPool() } private class GeometryPool { let cylinderGeometry: SCNCylinder let planeGeometry: SCNPlane init() { // Create shared geometries cylinderGeometry = SCNCylinder(radius: 0.125, height: 0.02) cylinderGeometry.materials.first?.diffuse.contents = UIColor.placeholderBackground planeGeometry = SCNPlane(width: 0.18, height: 0.18) planeGeometry.firstMaterial?.diffuse.contents = UIImage(systemName: "star.fill") planeGeometry.firstMaterial?.lightingModel = .constant } } func createGrid(size: Int, in scene: SCNScene) { // Remove existing grid gridNode?.removeFromParentNode() // Create a single parent node for the entire grid let newGridNode = SCNNode() // Create geometry instances once let cylinderGeometry = geometryPool.cylinderGeometry let planeGeometry = geometryPool.planeGeometry // Use SCNTransaction to batch updates SCNTransaction.begin() SCNTransaction.animationDuration = 0 let spacing = 1.0 let offset = Double(size-1) * spacing/2 // Pre-calculate transforms for better performance var transforms: [SCNMatrix4] = [] transforms.reserveCapacity(size * size) for row in 0..