6.2 C
New York
Tuesday, February 25, 2025

ios – I need assistance placing the colours appropriately in my Rubik’s dice check


I’m creating a 3D Rubik’s Dice utilizing SceneKit in Swift, and I’m encountering a difficulty the place the colours of the dice’s faces are usually not rendering as strong 3×3 faces as anticipated. As an alternative of every face of the 3x3x3 dice (e.g., the entrance face in inexperienced, the left face in orange, and many others.) being uniformly coloured throughout all 9 cublets, the colours seem fragmented or misplaced, usually displaying up in rows or columns quite than overlaying all the face. For instance, I see the inexperienced shade (meant for the entrance face, +Z) appropriately on the highest row, but it surely shifts to the underside row or adjoining faces as an alternative of forming a strong inexperienced 3×3 face.

Right here’s an summary of my setup and the difficulty:

  • Goal: I need every face of the Rubik’s Dice (entrance, again, left, proper, prime, backside) to be a strong shade for the 9 cublets that make up that face (e.g., all cublets with z = 1 ought to have their entrance face painted inexperienced).

  • Present Conduct: Colours are utilized partially or in fragmented patterns (e.g., a row of inexperienced on the prime, then a row of inexperienced under, however not a strong 3×3 inexperienced face). This occurs for all faces (crimson for +X, orange for -X, white for +Y, yellow for -Y, inexperienced for +Z, blue for -Z).

  • Suspected Concern: I believe the cublets (SCNBox) may be rotated, inflicting the supplies to use to the incorrect faces or within the incorrect orientation, however I’ve been unable to verify or repair this.

Right here is my code:

CubeScene:

import SwiftUI
import SceneKit

class CuboScene: SCNScene {
    override init() {
        tremendous.init()
        rootNode.eulerAngles = SCNVector3(0, 0, 0)  // Guarantee rootNode shouldn't be rotated
        rootNode.place = SCNVector3(0, 0, 0)  // Guarantee rootNode is on the origin
        rootNode.scale = SCNVector3(1, 1, 1)  // Guarantee no sudden scaling
        
//        let mild = SCNLight()
//        mild.kind = .omni
//        mild.depth = 2000
//        let lightNode = SCNNode()
//        lightNode.mild = mild
//        lightNode.place = SCNVector3(x: 5, y: 5, z: 5)
//        rootNode.addChildNode(lightNode)
        
        configureLights()
        createRubikCube()
    }
    
    personal func createRubikCube() {
        let measurement: CGFloat = 0.8
        let spacing: CGFloat = 1.05
        
        for x in -1...1 {
            for y in -1...1 {
                for z in -1...1 {
                    let cubelet = SCNBox(width: measurement, peak: measurement, size: measurement, chamferRadius: 0.0)  // No rounded edges
                    let cubeletNode = SCNNode(geometry: cubelet)
                    cubeletNode.place = SCNVector3(Float(x) * Float(spacing),
                                                     Float(y) * Float(spacing),
                                                     Float(z) * Float(spacing))
                    cubeletNode.eulerAngles = SCNVector3(0, 0, 0)  // Guarantee no rotation
                    print("Cubelet at place: ((Float(x) * Float(spacing)), (Float(y) * Float(spacing)), (Float(z) * Float(spacing)) with supplies: (getFaceMaterial(x: x, y: y, z: z).map { $0.diffuse.contents as? UIColor ?? .grey }) and eulerAngles: (cubeletNode.eulerAngles), rotation: (cubeletNode.rotation)")
                    
                    cubelet.supplies = getFaceMaterial(x: x, y: y, z: z)
                    rootNode.addChildNode(cubeletNode)
                }
            }
        }
    }
    
    personal func getFaceMaterial(x: Int, y: Int, z: Int) -> [SCNMaterial] {
        let colours: [UIColor] = [
            // Right face (+X): red if x = 1, gray for x = 0 or -1
            (x == 1) ? .red : .gray,
            // Left face (-X): orange if x = -1, gray for x = 0 or 1
            (x == -1) ? .orange : .gray,
            // Top face (+Y): white if y = 1, gray for y = 0 or -1
            (y == 1) ? .white : .gray,
            // Bottom face (-Y): yellow if y = -1, gray for y = 0 or 1
            (y == -1) ? .yellow : .gray,
            // Front face (+Z): green if z = 1, gray for z = 0 or -1
            (z == 1) ? .green : .gray,
            // Back face (-Z): blue if z = -1, gray for z = 0 or 1
            (z == -1) ? .blue : .gray
        ]
//        print("Place ((x), (y), (z)): Colours = (colours)")  // Debugging
        return colours.map { createMaterial(shade: $0) }
    }
    
    personal func createMaterial(shade: UIColor) -> SCNMaterial {
        let materials = SCNMaterial()
        print("Making use of materials with shade: (shade)")
        materials.diffuse.contents = shade.withAlphaComponent(1.0)
        materials.specular.contents = UIColor.white
        materials.shininess = 100
        materials.lightingModel = .phong
        
        return materials
    }
    
    personal func configureLights() {
        // Ambient mild for base illumination
        let ambientLight = SCNLight()
        ambientLight.kind = .ambient
        ambientLight.depth = 500
        let ambientLightNode = SCNNode()
        ambientLightNode.mild = ambientLight
        rootNode.addChildNode(ambientLightNode)

        // Array of positions and instructions for the 6 lights
        let positions: [(SCNVector3, SCNVector3)] = [
            (SCNVector3(0, 10, 0), SCNVector3(0, -1, 0)),  // Top
            (SCNVector3(0, -10, 0), SCNVector3(0, 1, 0)),   // Bottom
            (SCNVector3(10, 0, 0), SCNVector3(-1, 0, 0)),   // Right
            (SCNVector3(-10, 0, 0), SCNVector3(1, 0, 0)),   // Left
            (SCNVector3(0, 0, 10), SCNVector3(0, 0, -1)),   // Front
            (SCNVector3(0, 0, -10), SCNVector3(0, 0, 1))    // Back
        ]

        for (place, path) in positions {
            let mild = SCNLight()
            mild.kind = .directional
            mild.depth = 1000
            mild.shade = UIColor.white
            let lightNode = SCNNode()
            lightNode.mild = mild
            lightNode.place = place
            lightNode.eulerAngles = SCNVector3(
                atan2(path.y, path.z),
                atan2(path.x, path.z),
                0
            ) // Orient towards the middle
            rootNode.addChildNode(lightNode)
        }
    }
    
    required init(coder: NSCoder) {
        fatalError("init(coder:) has not been carried out")
    }
}

SceneKitView:

import SwiftUI
import SceneKit

struct SceneKitView: UIViewRepresentable {
    func makeUIView(context: Context) -> SCNView {
        let view = SCNView()
        view.scene = CuboScene()  // Use the created scene
        view.allowsCameraControl = true  // Permit digicam motion with contact
        view.autoenablesDefaultLighting = false  // Disable default lighting
        view.backgroundColor = .clear
        
        // Configure an preliminary digicam
        let cameraNode = SCNNode()
        cameraNode.digicam = SCNCamera()
        cameraNode.place = SCNVector3(x: 5, y: 5, z: 5)  // Diagonal place to see all faces
        cameraNode.look(at: SCNVector3(0, 0, 0))  // Level to the cubes heart
        view.pointOfView = cameraNode
        
        return view
    }

    func updateUIView(_ uiView: SCNView, context: Context) {}
}

#Preview {
    SceneKitView()
}

Right here is how the Rubik’s dice colours are producing:

enter image description here

I’ve tried a whole lot of various things, however I can’t make it proper.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles