How to draw the six surfaces with indivisual six colors ?

I belive followings are minimum code to create 3D cube via Craft.
How can I draw the six surfaces with indivisual six colors like a rubic cube ?
Thank you for your advice.

function setup()
    -- Dependencies    Craft, Camera
    scene = craft.scene()
    scene.camera.position = vec3(0, -10, 0)
    entity = scene:entity()
    entity.model = craft.model.cube(vec3(1,1,1))
    scene.camera:add(OrbitViewer, vec3(), 100, 0, 0)
end

function update(dt)
    scene:update(dt)
end

function draw()
	update(DeltaTime)
	scene:draw()
end

@cuvota Are you trying to draw a rubics cube or do you just want a cube with six different colored sides. I guess if you create one cube, you can create a lot more cubes to form a rubics cube. If no one posts anything, I’ll have an example a little later when I have time.

@cuvota Here’s an example of drawing 3x3x3 cubes.

function setup()    
    scene = craft.scene()   
    skyMaterial=scene.sky.material
    skyMaterial.sky=color(157, 215, 223, 255)
    skyMaterial.horizon=color(98, 165, 166, 255)
    scene.sun.rotation=quat.eulerAngles(-45,45,-90)
    v=scene.camera:add(OrbitViewer, vec3(0,0,0), 50, 0, 200)
    v.rx=45
    cubes()
end

function update(dt)
    scene:update(dt)
end

function draw()
    update(DeltaTime)
    scene:draw()	   
end

function cubes()    -- create 3x3x3 cubes
    for x=-1,1 do
        for y=-1,1 do
            for z=-1,1 do
                c = scene:entity()
                c.position=vec3(x*2.2,y*2.2,z*2.2)
                c.model = craft.model.cube(vec3(2,2,2))
                c.material = craft.material("Materials:Standard")
                col=color(math.random(255),math.random(255),math.random(255))
                c.material.diffuse=col
            end
        end
    end
end

@dave1707 That’s not going to work for a rubik’s cube because you have each cube as a separate colour, but for a rubik’s cube then each side of each cube will be a different colour.

Looking back at old Codea videos, I found a couple of rubik’s cubes:

https://youtu.be/BrHJ4hs9l0U

https://youtu.be/5tqwBvtFl0A

@LoopSpace I don’t know if he really wants to create a Rubiks cube or not, so I just gave him different colored cubes in 3x3x3 cube.

Here’s an example to color each side of a cube that can be used if he wants to create a Rubiks cube. I saw those videos when I did a forum search, but there wasn’t any code examples.

function setup() 
    col={color(255,0,0),color(0,255,0),color(0,0,255),
            color(255,255,0),color(255,0,255),color(0,255,255)}
    scene = craft.scene()   
    skyMaterial=scene.sky.material
    skyMaterial.sky=color(157, 215, 223, 255)
    skyMaterial.horizon=color(98, 165, 166, 255)
    scene.sun.rotation=quat.eulerAngles(-45,45,-90)
    v=scene.camera:add(OrbitViewer, vec3(0,0,0), 50, 0, 200)
    v.rx=45
    v.ry=45

    -- create a cube with different colored sides
    c = scene:entity()
    c.position=vec3(0,0,0)
    c.model = craft.model.cube(vec3(5,5,5))
    c.material = craft.material("Materials:Basic")
    for z=1,#c.model.colors do
        c.model:color(z,col[(z+3)//4])
    end
end

function update(dt)
    scene:update(dt)
end

function draw()
    update(DeltaTime)
    scene:draw()	   
end

Those videos are pre-craft so may not be relevant.

Here’s a change to the above code for a rubiks cube.

function setup() 
    col={color(255,0,0),color(0,255,0),color(0,0,255),
            color(255,255,0),color(255,0,255),color(0,255,255)}
    scene = craft.scene()   
    skyMaterial=scene.sky.material
    skyMaterial.sky=color(157, 215, 223, 255)
    skyMaterial.horizon=color(98, 165, 166, 255)
    v=scene.camera:add(OrbitViewer, vec3(0,0,0), 80, 0, 200)
    for x=-1,1 do
        for y=-1,1 do
            for z=-1,1 do
                sph(x*5.05,y*5.05,z*5.05)
            end
        end
    end
end

function update(dt)
    scene:update(dt)
end

function draw()
    update(DeltaTime)
    scene:draw()       
end

function sph(x,y,z)
    c = scene:entity()
    c.position=vec3(x,y,z)
    c.model = craft.model.cube(vec3(5,5,5))
    c.material = craft.material("Materials:Basic")
    for z=1,#c.model.colors do
        c.model:color(z,col[(z+3)//4])
    end
end

Thank you very much. I build basic structure of a 3 x 3 x 3 Rubic Cube shown the following picture. This is the first trial of using Craft, and found i’ts very powerful for 3D model creation. Next step is rotate each slice of the cube.

Greetings friends Impressive design, the use of textures and colors go excellent with the proposal. I think it’s great that they share this type of implementations in forums, all of us who go to this meeting place are in 3d design, scale model printers, prototypes and more. The future is here to stay! I would like to know if with this type of codes you could create other symmetry and of course take them to 3d scale

@3dmodels Using Craft, it’s a lot easier to create 3D objects.

l write following code to add cube rotation function as my study. but the method getting complex and hard to debug. This code have big problem . Is there more smart approach for this subject.?

function setup()
    frame = 1
    col={
        color(32, 255, 0, 255),
        color(237, 255, 0, 255),
        color(0,0,255),
        color(251, 251, 251, 255),
        color(255, 115, 0, 255),
        color(255, 0, 41, 255)
    }
    scene = craft.scene()   
    skyMaterial=scene.sky.material
    skyMaterial.sky=color(157, 215, 223, 255)
    skyMaterial.horizon=color(98, 165, 166, 255)
    v=scene.camera:add(OrbitViewer, vec3(0,0,0), 80, 0, 200)
    v.rx,v.ry=20,20
    
    -- cubes table
    -- cube[][1] sph instance
    --       [2] current position
    --       [3] current ratation angle
    cubes={}
    for x=-1,1 do
        for y=-1,1 do
            for z=-1,1 do
                cp=vec3(x*5.05,y*5.05,z*5.05)
                rt=vec3(0,0,0)
                table.insert(cubes, {sph(cp.x,cp.y,cp.z),cp,rt})
            end
        end
    end
    dlt = 1
    cyc =90
    round=3600
    rotvec=vec3(0,0,0)
    rotvec.z =1
    slice= -1
end

function rotateFlag(pos, vec, sl)
    level=( pos.x* vec.x + pos.y* vec.y+ pos.z* vec.z)
    if level > 0.5 and sl==1then
        return true
    elseif level < -0.5 and sl==-1 then
        return true
    elseif sl==0 and math.abs(level) < 0.5 then
        return true
    else
        return false
    end
end

function rotateAngle(ang, vec, agl)
    ret= ang * vec+ agl
    return ret.x,ret.y,ret.z
end

function scalarRotateAngle(ang, vec, agl)
    ret= ang * vec
    return ret.x - ret.y + ret.z
end

function stepAngle(ang,vec,agl)
     return ang * vec + agl
end

function rotateInput(vec, stpos, sra)
    if math.abs(vec.z)==1 then
        ret = vec2(stpos.x, stpos.y)
        rot=ret:rotate(math.rad(sra))
        prod=vec3(rot.x,rot.y,stpos.z)
    elseif math.abs(vec.y)==1 then
        ret = vec2(stpos.z, stpos.x)
        rot=ret:rotate(math.rad(sra))
        prod=vec3(rot.x, stpos.y, rot.y)
    elseif math.abs(vec.x)==1 then
        ret = vec2(stpos.z, stpos.y)
        rot=ret:rotate(math.rad(sra))
        prod=vec3(stpos.x, rot.x,rot.y)
    end
    return prod
end

function update(dt)
    for k,v in ipairs(cubes) do
        if rotateFlag(v[1].position, rotvec,slice) then
            sra = scalarRotateAngle(frame,rotvec,v[3])
            v[1].rotation=quat.eulerAngles(rotateAngle(frame,rotvec,v[3]))
            v[1].position= rotateInput(rotvec, v[2], sra)
            if (frame % cyc) == 0 then
                v[2]= rotateInput(rotvec,v[2], sra)
                v[3] = stepAngle(90,rotvec,v[3])
                -- print("v3=",v[2], v[3],v[1].position)
                -- print(cubes[k][3].z)
            end
        end
    end
    scene:update(dt)
    
    -- vary parameters for testing
    -- frame : count draw() event
    -- rotvec : rotation direction vector
    --          must be either (0,0,1),(0,1,0),(1,0,0)
    -- slice : cube group (1,?,?),(0,?,?), .....
    if (frame % 90) == 0 then
        frame=1
        rotvec=vec3(rotvec.y, rotvec.z,rotvec.x)
        rotvec=vec3(rotvec.y, rotvec.z,rotvec.x)
        if rotvec.x == 1 then
            slice = (slice + 1)
            if slice==2 then
                slice=-1
            end
        end
    end
    frame = frame + dlt
end

function draw()
    update(DeltaTime*5)
    scene:draw() 
end

function sph(x,y,z)
    c = scene:entity()
    c.position=vec3(x,y,z)
    c.model = craft.model.cube(vec3(5,5,5))
    c.material = craft.material("Materials:Basic")
    for z=1,#c.model.colors do
        c.model:color(z,col[(z+3)//4])
    end
    return c
end

It’s been a while since I wrote my Rubik’s cube (in the pre-Craft days), but I think that I had a table for each face and so when rotating a face, I could apply a single quaternion to each cube in that table. Then I’d update the tables since the cubes will have moved round. To be clear, a cube would typically belong to more than one face-table.

If you think that the code would be useful, I can upload it to github.

Yes please. I’ts would be helpful.
And I also wanna find the method using Craft. I suppose making 9 cubes as a group and rotate the whole of the group around the center of it.

Is there a notion of a Craft group? I know that entities can have parents, but that wouldn’t work for a rubik’s cube because you’d have to be continually shifting parents and tracking which face was being rotated at a time.

@cuvota Making 9 cubes as a group and rotating it won’t work because the corner cubes can be rotated in different groups.

@dave1707 i just said “OMG, it’s coloring the vertices!” :slight_smile:

Not sure about this post, but I’ll use the dice example from the other discussion to show a cube with different colors on each side.

displayMode(FULLSCREEN)

function setup()
    noSmooth()
    rectMode(CORNER)
    
    img=image(600,100)    
    setContext(img)
    
    fill(255,0,0)
    rect(0,0,100,100)
    fill(33, 255, 0, 255)
    rect(100,0,100,100)
    fill(22, 0, 255, 255)
    rect(200,0,100,100)
    fill(255, 230, 0, 255)
    rect(300,0,100,100)
    fill(255, 0, 167, 255)
    rect(400,0,100,100)
    fill(0, 255, 221, 255)
    rect(500,0,100,100)
    setContext()
        
    assert(OrbitViewer, "Please include Cameras (not Camera) as a dependency")
    
    scene = craft.scene()
    m = scene:entity()
    m.model = craft.model.cube(vec3(1,1,1))
    m.material = craft.material("Materials:Specular")
    m.material.map = img  
      
    uvs1={}
    c=0
    for x=1,6 do
        table.insert(uvs1,vec2(c/6,0))
        table.insert(uvs1,vec2((c+1)/6,0))
        table.insert(uvs1,vec2((c+1)/6,1))
        table.insert(uvs1,vec2(c/6,1))
        c=c+1
    end
    m.model.uvs=uvs1
    
    viewer = scene.camera:add(OrbitViewer, vec3(0), 10, 0, 2000)
    viewer.camera.farPlane=3000
end

function update(dt)
    scene:update(dt)
end

function draw()
    update(DeltaTime)
    scene:draw() 
    sprite(img,WIDTH/2,HEIGHT-100)   
end

@RonJeffries - yup, if you build up a mesh for the texture, using triangles, different colours at the vertices will produce colour gradients so you can produce quite complex images.