Request for simple voxel example

Tried to read the docs, got confused, but would like to see a small example of using voxels. How do I make a small scene with say two voxels of a solid color? The documentation is a bit confusing, and some examples on the site uses addAssetPack which isnt documented.

But I would like to just add some colored voxels to a volume without texture and try it out a bit :slight_smile:

I know how to make it with meshes, but not with craft :).

@tnlogy Here’s an example I have that uses voxels.

viewer.mode=FULLSCREEN

function setup()
    fill(255)
    assert(OrbitViewer, "Please include Cameras (not Camera) as a dependency")
    scene = craft.scene() 
    v=scene.camera:add(OrbitViewer,vec3(50,200,0), 500, 0, 2000)
    v.camera.farPlane=10000
    v.rx=30
    v.ry=30
    scene.voxels.blocks:addAssetPack("Blocks")
    dirtgrass = scene.voxels.blocks:new("DirtGrass")
    dirtgrass.setTexture(ALL, "Blocks:Dirt Grass")
    water = scene.voxels.blocks:new("Water")
    water.setTexture(ALL, "Blocks:Water")
    snow = scene.voxels.blocks:new("Snow")
    snow.setTexture(ALL, "Blocks:Snow")
    grass = scene.voxels.blocks:new("Grass Top")
    grass.setTexture(ALL, "Blocks:Grass Top")
    
    scene.voxels.visibleRadius=30
    scene.voxels:resize(vec3(30,1,30))          
    scene.voxels.coordinates = vec3(100,0,100) 

    offsetX=6
    offsetZ=4
    
    dirtLevel=80
    grassLevel=50
    waterLevel=7
        
    val=400
    m=1/val
    h=craft.noise.perlin()

    xx,zz=0,0  
    for x=1,val do
        xx=xx+m
        zz=0
        for z=1,val do  
            zz=zz+m
            y=math.abs(h:getValue(xx+offsetX,0,zz+offsetZ))*100//1
            if y>dirtLevel then
                scene.voxels:fill("Snow")
                scene.voxels:block(x,y,z)
            elseif y>grassLevel then
                scene.voxels:fill("DirtGrass")
                scene.voxels:block(x,y,z)
            elseif y>waterLevel then
                scene.voxels:fill("Grass Top")
                scene.voxels:block(x,y,z)
            else
                scene.voxels:fill("Water")
                scene.voxels:block(x,waterLevel,z)
            end
        end
    end
end

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

function draw()
    update(DeltaTime)
    scene:draw()
    text("Use one finger to rotate.",WIDTH/2,HEIGHT-25)
    text("Use two fingers to move or resize.",WIDTH/2,HEIGHT-50)
end

Thanks for the code, but I wanted to know if you could make voxels of solid color or are only textured supported?

@tnology - have you tried the Craft demos - in one of them you can build your own scene and can build your own blocks, They are then stored in a grid for selection. I think it’s called block library. So if you check out the code you may be able to design your own project.

@tnlogy Heres another example that might be closer to what you want if you’re still looking for an example. I tried to keep it as small as possible. It creates a red and blue sprite in the Dropbox folder. Once the sprites are created, you can comment or remove those 2 lines.

viewer.mode=FULLSCREEN

function setup()
    --create red and blue sprite in Dropbox
    --comment out or remove the next 2 lines after the first run
    createColor("Red",color(255,0,0))
    createColor("Blue",color(0,0,255))
    
    assert(OrbitViewer, "Please include Cameras as a dependency")
    
    scene = craft.scene() 
    scene.camera:add(OrbitViewer,vec3(7,7,0), 20, 0, 10000) 
    scene.voxels.visibleRadius=90
    scene.voxels:resize(vec3(60,1,60))
    scene.voxels.coordinates = vec3(0,0,0)
    
    --add as asset packs    
    scene.voxels.blocks:addAssetPack("Blocks")
    scene.voxels.blocks:addAssetPack("Dropbox")
     
    --define Red and Blue colors       
    temp=scene.voxels.blocks:new("Red")
    temp.setTexture(ALL, "Dropbox:Red") 
     
    temp=scene.voxels.blocks:new("Blue")
    temp.setTexture(ALL, "Dropbox:Blue") 
     
    --draw 6 blocks of each color           
    for z=1,6 do
        scene.voxels:fill("Red")
        scene.voxels:block(7,z*2,0) 
           
        scene.voxels:fill("Blue")
        scene.voxels:block(z*2,7,0)
    end    
end

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

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

function createColor(name,col)
    img=image(128,128)
    setContext(img)
    background(col)
    setContext()
    saveImage(asset.documents.Dropbox..name,img)
end

Thanks! After seeing your example and digging in some example code it made a new version


viewer.mode=FULLSCREEN

function setup()    
    assert(OrbitViewer, "Please include Cameras as a dependency")
    
    scene = craft.scene()    scene.camera:add(OrbitViewer,vec3(7,7,0), 20, 0, 10000)
    scene.voxels.visibleRadius=90
    scene.voxels:resize(vec3(60,1,60))
    scene.voxels.coordinates = vec3(0,0,0)
    blank = scene.voxels.blocks:new("Blank")
    blank.setTexture(ALL, "Blocks:Blank White")
    blank.tinted = true
    
    
    --draw 6 blocks of each color
    for z=1,6 do
        local c = color(255, 0, 106)
        scene.voxels:set(7,z*2,0,"name","Blank","color", c)
        c = color(20, 0, 255)
            scene.voxels:set(z*2,7,0,"name","Blank","color", c)
    end
end

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

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

This uses tinted instead. I find the documentation for Craft a bit lacking and confusing compared to the documentation of the other parts of Codea. Thanks a lot for the help in understanding!

@tnlogy I like your version. I never used voxels:set, so something new. I agree that the docs sometimes don’t give enough info on how to use things.

Seems like you can to like this also:


        scene.voxels:fill("name","Blank",
        "color",color(154, 233, 80))
        scene.voxels:block(7,z*2,1)

@tnlogy Heres an example of a Sierpinski cube using the voxel color code you used above. Uncomment the color lines near the bottom of the code to see different color schemes.

viewer.mode=FULLSCREEN

function setup()
    ss=27         -- cube size, powers of 3 only (3, 9, 27, 81)
    fill(255)
    assert(OrbitViewer, "Please include Cameras (not Camera) as a dependency")
    scene = craft.scene() 
    scene.voxels.visibleRadius=90
    scene.voxels:resize(vec3(30,1,30))
    scene.voxels.coordinates = vec3(ss,ss,ss)
    v=scene.camera:add(OrbitViewer,vec3(ss,ss,ss), ss*3, 0, 6000) 
    v.rx=45
    v.ry=45    
    blank = scene.voxels.blocks:new("Blank")
    blank.setTexture(ALL,"Blocks:Blank White")
    blank.tinted=true        
    count=0
    cube(0,0,0,ss)
end

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

function draw()
    update(DeltaTime)
    scene:draw()
    text("Cube size "..ss.."x"..ss.."x"..ss.." = "..(ss^3).." cubes",WIDTH/2,HEIGHT-25)
    text("Number of cubes drawn "..count,WIDTH/2,HEIGHT-50)
    text("Sierpinski cube",WIDTH/2,HEIGHT-75)
end

function cube(x,y,z,size)
    local s=size//3
    for x1=-s,s,s do
        for y1=-s,s,s do
            for z1=-s,s,s do
                if (y1~=0 or z1~=0) and (x1~=0 or z1~=0) and (x1~=0 or y1~=0) then
                    if size~=3 then
                        cube(x1+x,y1+y,z1+z,s)
                    else
                        count=count+1
                        r=255//(x1+s+1)
                        g=255//(y1+s+1)
                        b=255//(z1+s+1)
                        c=color(r,g,b)        
                        --c=color(200,200,200)   
                        --c=color(math.random(255),math.random(255),math.random(255))
                        scene.voxels:set((x1+x+ss),(y1+y+ss),(z1+z+ss),
                                "name","Blank","color", c)
                    end
                end
            end
        end
    end
end

Nice! :slight_smile: