Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

I found craft.voxels to be an excellent system and tried to organize its hierarchy

edited January 19 in Codea Craft Posts: 190

I recently spent some time studying craft.voxels and found that it was well designed, but it didn’t seem to have many users working on formal projects, and I wanted to use it to develop an educational app, but in the process of learning to use it encountered many difficulties, but also some gains. I’d like to share it here so that more users are interested in craft.voxels and we can talk about all the voxels issues together.

For everyone who wants to get to know craft.voxels better, here’s a document I’ve compiled of all the voxels’available functions. This is the most comprehensive information I have been able to gather so far. If you know something I missed, please add it. Thank you.

The hierarchy of Voxels system

The `Voxels system has three levels:

  • voxel:craft.voxels
  • block:craft.blocks
  • volume:craft.volume

voxels is the most basic unit and provides many basic properties and methods:

  • read-only property:

    • blocks
    • visibleChunks
    • generatingChunks
    • meshingChunks
  • read-write property:

    • coordinates
    • visibleRadius
  • method:

    • resize()
    • set()
    • get()
    • fill()
    • fillstyle
    • find()
    • block()
    • sphere()
    • box()
    • line()
    • updateBlock()
    • raycast()
    • generate()
    • isRegionLoaded()
    • iterateBounds()
    • enableStorage()
    • disableStorage()
    • deleteStorage()

    Based on craft.voxelscraft.blocks,made up of multiple voxels, there are two types:

  • The default block type built into the system:

    • SOLID
    • EMPTY
  • User-defined type of box: freely named

For user-defined block type, Have the following properties and methods:

  • read-only property:

    • id
    • name
    • state
    • model
  • read-write property:

    • geometry
    • renderPass
    • tinted
    • dynamic
    • scripted
  • position property:

    • x
    • y
    • z
  • method:

    • setTexture()
    • setColor()
    • craft.block.directionToFace()
    • craft.block.faceToDirection()

Because block type supports scripting, there are methods that can only be used for scripting:

  • methods for blockType internal scripts:

    • blockType:created()
    • blockType:destroyed()
    • blockType:buildModel()
    • blockType:placed()
    • blockType:interact()
    • blockType:blockUpdate()
    • blockType:update()
    • set()
    • get()
    • schedule()
    • xyz()
  • block.state provides the method:

    • blockType.state.addFlag()
    • blockType.state.addRange()
    • blockType.state.addList()
  • block.model provides the method:

    • clear()
    • rotateY()
    • rotateX()
    • addElement() There are special parameters required(I am not so clear if there are other parameters?)
      - lower = vec3(128,128,128)
      - upper = vec3(255,255,255)
      - collision = STEP
      - textures = "Blocks:Grass"
      - ao = false

craft.volume is the higher level of abstraction provided by the craft.voxels` system, which is designed as a component that can be attached to an entity (providing three forms of syntax for attaching) . It provides the following properties and methods:

  • property:

    • model
  • method:

    • size()
    • get ()
    • set ()
    • raycast ()
    • clear ()
    • resize ()
    • load ()
    • save ()
    • loadSnapshot ()
    • saveSnapshot ()
    • blockID ()
    • setWithNoise ()
    • updateBlock ()

There is also a constructor:VolumeSnapshot()

An global method: bounds(min, max)

  • read-only property:
    - min: vec3
    - max: vec3
    - valid: Boolean
    - center: vec3
    - offset: vec3
    - size:
  • method:
    - intersects(),
    - encapsulate(),
    - translate(),
    - set()
Tagged:
«1

Comments

  • Posts: 190

    Some of the above content appears in the built-in help documentation, and some does not appear in the built-in help documentation, but appears in the sample code

  • edited January 12 Posts: 190

    I will try to write some of the simplest sample code, to let a novice know where to start, step by step, I will try to reduce the complexity of the sample code

    Example1 The simplest voxel routines keep only those things that can’t be deleted.

    The code is below:

    -- ExEzVoxel
    viewer.mode = FULLSCREEN
    
    function setup()
        scene = craft.scene()
    
        player = scene.camera:add(OrbitViewer, vec3( 40, 20, 40), 8, 1, 400)
    
        -- 设置 voxel 地形参数:大小规模和坐标
        scene.voxels:resize(vec3(5,1,5))      
        scene.voxels.coordinates = vec3(0,0,0)    
    
        -- 使用 craft.voxels 默认提供的基础 block type:SOLID
        scene.voxels:fill("SOLID")
    
        -- 用默认的方块 SOLID 创建地面,球体,线条,单独的方块
        scene.voxels:box(0,0,0, 16*8,10,16*8)
        scene.voxels:sphere(40,50,90,16*2)
        scene.voxels:line(10,20,0,10,50,30)
        scene.voxels:block(vec3(30,20,35))
    
        craft.scene.main = scene
    end
    

    https://youtu.be/NYM5vJvSuN8

  • Posts: 190

    Example 2 Using user-defined block type

    the code:

    -- ExEzVoxel
    
    viewer.mode = FULLSCREEN
    
    function setup()
        scene = craft.scene()
    
        player = scene.camera:add(OrbitViewer, vec3( 40, 20, 40), 8, 1, 400)
    
        -- 设置 voxel 地形参数:大小规模和坐标
        scene.voxels:resize(vec3(5,1,5))      
        scene.voxels.coordinates = vec3(0,0,0)    
    
        -- Using default block type: SOLID 
        scene.voxels:fill("SOLID")
    
        -- create a box using "Solid" block type
        scene.voxels:box(0,0,0, 16*8,10,16*8)
    
        -- Create user-defined block type
        scene.voxels.blocks:addAssetPack("Blocks")
        local dirt = scene.voxels.blocks:new("myDirt")
        dirt.setTexture(ALL, "Blocks:Dirt")
        dirt.setColor(ALL, color(239, 222, 5))
    
        scene.voxels:fill("myDirt")
        scene.voxels:sphere(40,50,90,16*2)
        scene.voxels:line(10,20,0,10,50,30)
        scene.voxels:block(vec3(30,20,35))
    
        craft.scene.main = scene
    end
    

    https://youtu.be/NRATwYXFuY4

  • Posts: 190

    Example 3 Using the most simplest internal script

    The code:

    viewer.mode = FULLSCREEN
    
    function setup()
        scene = craft.scene()
    
        player = scene.camera:add(OrbitViewer, vec3( 40, 20, 40), 8, 1, 400)
    
        -- 设置 voxel 地形参数:大小规模和坐标
        scene.voxels:resize(vec3(5,1,5))      
        scene.voxels.coordinates = vec3(0,0,0)    
    
        -- Using default block type: SOLID 
        scene.voxels:fill("SOLID")
    
        -- create a box using "Solid" block type
        scene.voxels:box(0,0,0, 16*8,10,16*8)
    
        -- Create user-defined block type
        scene.voxels.blocks:addAssetPack("Blocks")
        local dirt = scene.voxels.blocks:new("myDirt")
        dirt.setTexture(ALL, "Blocks:Dirt")
        dirt.setColor(ALL, color(239, 222, 5))
        dirt.tinted = true
        dirt.scripted = true
    
        function dirt:created()
            -- Randomise colour based on location
            local x,y,z = self:xyz()
            math.randomseed(x * y * z)
            local c =color(math.random(128,255), math.random(128,255), math.random(128,255))
            self.voxels:set(x,y,z,"color", c)
        end
    
        scene.voxels:fill("myDirt")
        scene.voxels:sphere(40,50,90,16*2)
        scene.voxels:line(10,20,0,10,50,30)
        scene.voxels:block(vec3(30,20,35))
    
        craft.scene.main = scene
    end
    

    https://youtu.be/zYFlhw88ZPA

  • dave1707dave1707 Mod
    Posts: 9,808

    @binaryblues Very interesting and helpful.

  • Posts: 239

    my main focus would be how many voxels can you get on the screen at once and how complex of a scene can you render with them? the current usage as a minecraft style world is great but limited, i’ve seen some cool destruction demos using voxels in unity, how close can we get to that?

  • edited January 12 Posts: 190

    @dave1707 Glad to hear that. I’m emulating your short, pithy way of demonstrating code, I find this style of coding particularly helpful for beginners.

    @skar Depending on how complex a custom block type is, the more complex a single block is, the more resources it consumes. As far as my demo is concerned, you can test the approximate answer to the first question (using the simplest Solid block type) by modifying the parameters of this code:

    scene.voxels:resize(vec3(5,1,5))
    scene.voxels:box(0,0,0, 16*8,10,16*8)
    

    try to change it:

    scene.voxels:resize(vec3(5,5,5))
    scene.voxels:box(0,0,0, 16*20,16*2,16*20)
    

    As for the second question, i don’t know how to clearly define the complexity of the scene, but I can only make it subjective based on the actual rendering speed in programming. Finally, I think it can be completely duplicated, there is no inherent limitation. I might add that static scenes shouldn’t be too much of a problem, but the smoke and shadows can be a bit difficult because I’m not quite sure how to use shaders in voxels yet, i’m still trying to familiarize myself with the voxels system, so maybe when I get to know the voxels system a little better, I’ll have a solution.

  • dave1707dave1707 Mod
    Posts: 9,808

    @skar I was able to draw over 15,000,000 voxel cubes before Codea crashed.

  • dave1707dave1707 Mod
    Posts: 9,808

    @binaryblues I think very simple examples are the best way for beginners. Just a few things in simple terms that are easy to figure out. Large, complicated examples are great to show the power of what can be done, but it’s very difficult to understand and figure out what’s happening or how to do something.

  • Posts: 2,574

    @binaryblues - trying to zoom your second and third Voxel demos with finger and thumb, with some rotation, and it crashed Codea. Reported to dev team via crash report - not sure if this is a feature of Craft or how you have set up your demos. I have been playing with your demos but the crashes occurred both with your demos and my own fiddling with your code.

    But, your demos are very good, interesting, especially with your approach to building up a scene with minimal code. I don’t recognise the structures you build in them - any chance you can give a more detailed description of the third demo I’d like to be able to build code like that myself but I.m still low on the learning curve with Craft/Voxels.

    Thanks for the demos.

  • dave1707dave1707 Mod
    Posts: 9,808

    @Bri_G @binaryblues Tried the 2nd and 3rd examples with no problems. Was able to zoom and rotate.

  • Posts: 2,574
    @dave1707 - it didn't crash straight away, I rotated the sphere front to be facing the camera the tried to zoom in. In the process the sphere tended to rotate slightly from left to right and the crash occured then
  • Posts: 190

    @dave1707 I completely agree with you, and I always try out all the sample code you posted on the forums. Simple examples show basic functionality, and more complex examples provide an advanced template for beginners, so it’s important to find a balance between the two to help document writers, and Thanks for your tests.

    @Bri_G Thanks to your testing, On my iPad it didn’t crash. When I ran the other projects, there will be a one-click run on the crash situation. I’ve omitted a lot of settings in these sample programs, and for the sake of reducing complexity, I’ll add new content bit by bit to make it easier for new users to understand. Also, I added some comments to the latest example, so if you’re not sure what line of code you want to use, mention it, and I’ll explain it.

  • edited January 13 Posts: 190

    Example4: Using blockUpdate() to show some blink block.
    An interesting thing, if I draw a whole sphere, it can not blink, but if I draw half sphere, it can blink, the same size.

    In this example I made some changes:

    • I’ve saved a few comment lines for the experiment, and you can try turning them on and off to see what happens.
    • To make it easier to write an internal script for the block, the code that creates the block type is extracted and written as a separate function.
    • Return to normal Codea Craft code structure: setup(), update(dt), draw()

    The code:

    viewer.mode = FULLSCREEN
    
    function setup()
        scene = craft.scene()
    
        player = scene.camera:add(OrbitViewer, vec3( 40, 20, 40), 8, 1, 400)
    
        -- set voxel terrain parameters: size, coord
        scene.voxels:resize(vec3(5,1,5))      
        scene.voxels.coordinates = vec3(0,0,0)    
    
        -- Using default block type: SOLID as the filling unit
        scene.voxels:fill("solid")
    
        -- Create a box using "Solid" block type, every unit in the box is a "solid" block
        scene.voxels:box(0,0,0, 16*8,10,16*8)
    
        -- Create a new block type "myDirt"    
        newBlockTypeDirt()
    
        scene.voxels:fill("myDirt")
        -- A sphere larger than half can not blink, so interesting
        scene.voxels:sphere(40,20,77,8)
        -- Half sphere can blink
        scene.voxels:sphere(10,20,0,8)
        scene.voxels:line(10,20,0,10,50,30)
        scene.voxels:block(vec3(30,20,35))
    
        -- craft.scene.main = scene
    end
    
    function newBlockTypeDirt()
        -- Create user-defined block type
        scene.voxels.blocks:addAssetPack("Blocks")
        local dirt = scene.voxels.blocks:new("myDirt")
        dirt.setTexture(ALL, "Blocks:Dirt")
        dirt.setColor(ALL, color(239, 222, 5))
        dirt.tinted = true
        dirt.scripted = true
        dirt.state:addFlag("on", false)
    
        -- The internal script
        function dirt:created()
            self:schedule(60)
            self:set(COLOR, color(108, 233, 80))
        end
    
        function dirt:blockUpdate()
            -- Randomise colour based on location
            -- local x,y,z = self:xyz()
            -- math.randomseed(x * y * z)
            local c =color(math.random(128,255), math.random(128,255), math.random(128,255))
            -- self.voxels:set(x,y,z,"color", c)
            self:set(COLOR, c)
            self:schedule(10)
        end
    
        return dirt
    end
    
    function update(dt)
        scene:update(dt)
    end
    
    function draw()
        update(DeltaTime)    
        scene:draw()
    end
    

    https://youtu.be/V-rIO80-Vm4

  • edited January 13 Posts: 2,574

    @binaryblues - hmmmm, couldn’t crash this. Wonder if it’s down to the following line in the other examples.

    craft.scene.main = scene
    

    Thanks for this, the comments are very helpful.

  • edited January 13 Posts: 190

    Example5: Using the craft standard model--craft.model() to custom the model of block type.

    Block type has three modeling methods:
    - one is to use the craft model,
    - the other is to use the block’method addElement() to customize the block type model.
    - the 3rd one is procedural generation

    The first involves loading the physical system manually, using these lines of code:

    self.top:add(craft.rigidbody, STATIC)
    self.top:add(craft.shape.box, vec3(0.8,0.8,0.8), offset or vec3(0.4,0.4,0.4))
    

    The second can use the craft.voxels system has been set up, do not need to manually load. With craft.model, you can provide an unrestricted look and feel for blocks, you can use a variety of textures and textures, and you can use custom shaders for maximum freedom, but all of this requires you to write your own processing code.

    Here I demonstrate the use of craft.model to model blocks:

    The code:

    viewer.mode = FULLSCREEN
    
    function setup()
        scene = craft.scene()
        scene.sky.material.sky = color(80, 203, 233)
        scene.sky.material.horizon = color(80, 108, 233)
    
        player = scene.camera:add(OrbitViewer, vec3( 40, 20, 40), 8, 1, 400)
    
        -- set voxel terrain parameters: size, coord
        scene.voxels:resize(vec3(5,1,5))      
        scene.voxels.coordinates = vec3(0,0,0)    
    
        -- Using default block type: SOLID as the filling unit
        scene.voxels:fill("solid")
    
        -- Create a box using "Solid" block type, every unit in the box is a "solid" block
        scene.voxels:box(0,0,0, 16*8,10,16*8)
    
        -- Create a new block type "myDirt"    
        newBlockTypeDirt()
    
        -- Create a new block type "myDirt", using craft model
        newBlockTypeDirtMWithCraftModel()
    
        scene.voxels:fill("myDirt")
        -- A sphere larger than half can not blink, so interesting
        scene.voxels:sphere(40,20,77,8)
        -- Half sphere can blink
        scene.voxels:sphere(10,20,0,8)
        scene.voxels:line(10,20,0,10,50,30)
    
        -- Building model
        scene.voxels:fill("myDirtModel1")   
        scene.voxels:block(vec3(30,20,35))
        scene.voxels:line(40,20,30,10,50,30)
        scene.voxels:sphere(70,20,77,2)
    
        -- craft.scene.main = scene
    end
    
    
    function newBlockTypeDirtMWithCraftModel()
        local dirt = scene.voxels.blocks:new("myDirtModel1")
        dirt.dynamic = true
        dirt.scripted = true
        dirt.geometry = TRANSPARENT
    
        -- The internal script
        function dirt:created()
            e = self.entity
            self.base = scene:entity()
            self.base.parent = e
            self.base.position = vec3(0.5, 0.3, 0.5)
            local r = self.base:add(craft.renderer, craft.model.cube(vec3(2.8,0.6,2.8)))
            r.material = craft.material(asset.builtin.Materials.Specular)
            r.material.diffuse = color(133, 79, 30, 255)
            r.material.map = readImage(asset.builtin.Blocks.Brick_Grey)
    
            self.top = scene:entity()
            self.top.parent = e
            self.top.position = vec3(0.1, 0.6, 0.1)
            local r2 = self.top:add(craft.renderer, craft.model.cube(vec3(2.8,0.2,2.8), vec3(1.4,0.1,1.4)))
            -- local r2 = self.top:add(craft.renderer, craft.model(asset.builtin.Primitives.Monkey))
            r2.material = craft.material(asset.builtin.Materials.Specular)
            r2.material.diffuse = color(66, 47, 30, 255)
            r2.material.map = readImage(asset.n0)
            r2.material.normalMap = readImage(asset.n1)
            self.angle = 0
        end
    
        -- Because of using the craft standard model(craft.model.cube), here’s update()
        function dirt:update()
            self.top.rotation = quat.eulerAngles(0,  self.angle+ElapsedTime*100, 0)
        end
    
        return dirt
    end
    
    function newBlockTypeDirt()
        -- Create user-defined block type
        scene.voxels.blocks:addAssetPack("Blocks")
        local dirt = scene.voxels.blocks:new("myDirt")
        dirt.setTexture(ALL, "Blocks:Dirt")
        dirt.setColor(ALL, color(239, 222, 5))
        dirt.tinted = true
        dirt.scripted = true
        dirt.state:addFlag("on", false)
    
        -- The internal script
        function dirt:created()
            self:schedule(60)
            self:set(COLOR, color(108, 233, 80))
        end
    
        function dirt:blockUpdate()
            -- Randomise colour based on location
            -- local x,y,z = self:xyz()
            -- math.randomseed(x * y * z)
            local c =color(math.random(128,255), math.random(128,255), math.random(128,255))
            -- self.voxels:set(x,y,z,"color", c)
            self:set(COLOR, c)
            self:schedule(10)
        end
    
        return dirt
    end
    
    function update(dt)
        scene:update(dt)
    end
    
    function draw()
        update(DeltaTime)    
        scene:draw()
    end
    

    https://youtu.be/GVzNfEIydWk

    Here using a loaded model, you can use any obj model:

    https://youtu.be/dN0K1PIBpu0

  • Posts: 190

    @Bri_G A good news! Nice to hear that.

  • Posts: 239

    can you use any model as the base voxel? it doesn’t have to be a box right?

  • Posts: 190

    @skar So far it looks like you can use any model as your own basic block type unit, and the craft.voxels system provides this capability.The only thing you need to think about is performance

  • Posts: 190

    Example6: Using addElement() to build block type model

    Btw. I am not so clear about these lines:

    collision = STEP,        
    ao = false
    

    The code:

    viewer.mode = FULLSCREEN
    
    function setup()
        scene = craft.scene()
        scene.sky.material.sky = color(80, 203, 233)
        scene.sky.material.horizon = color(80, 108, 233)
    
        player = scene.camera:add(OrbitViewer, vec3( 40, 25, 40), 8, 1, 400)
    
        -- set voxel terrain parameters: size, coord
        scene.voxels:resize(vec3(5,1,5))      
        scene.voxels.coordinates = vec3(0,0,0)    
    
        -- Using default block type: SOLID as the filling unit
        scene.voxels:fill("solid")
    
        -- Create a box using "Solid" block type, every unit in the box is a "solid" block
        scene.voxels:box(0,0,0, 16*8,10,16*8)
    
        -- Create a new block type "myDirt"    
        newBlockTypeDirt()
    
        -- Create a new block type "myDirtModel1", using craft model
        newBlockTypeDirtWithCraftModel()
    
        -- Create a new block type "myDirtModel2", using addElement() to build model
        newBlockTypeDirtWithAddElement()
    
        scene.voxels:fill("myDirt")
        -- A sphere larger than half can not blink, so interesting
        scene.voxels:sphere(40,20,77,8)
        -- Half sphere can blink
        scene.voxels:sphere(10,20,0,8)
        scene.voxels:line(10,20,0,10,50,30)
    
    
        -- Building model
        scene.voxels:fill("myDirtModel2")   
        scene.voxels:block(vec3(30,20,35))
        scene.voxels:line(40,20,30,10,50,30)
        scene.voxels:sphere(70,20,77,2)
    
        -- craft.scene.main = scene
    end
    
    
    function newBlockTypeDirtWithAddElement()
        local dirt = scene.voxels.blocks:new("myDirtModel2")    
        dirt.setTexture(ALL, "Blocks:Dirt")
        -- dirt.setColor(ALL, color(227, 89, 14))
        dirt.scripted = true
    
        -- custom model from state
        function dirt:buildModel(model)
            model:clear()
            model:addElement
            {
                lower = vec3(0,0,0),
                upper = vec3(255,80,255), 
                textures = "Blocks:Wood",   
                collision = STEP,        
                ao = false
            }
    
            model:addElement
            {
                lower = vec3(0,60,0),
                upper = vec3(156,156,190),  
                textures = "Blocks:Stone", 
                collision = STEP,   
                ao = false
            }  
    
            model:addElement
            {
                lower = vec3(0,0,0),
                upper = vec3(106,255,100),  
                textures = "Blocks:Dirt", 
                collision = STEP,   
                ao = false
            }  
        end
    
        return dirt
    end
    
    function newBlockTypeDirtWithCraftModel()
        local dirt = scene.voxels.blocks:new("myDirtModel1")
        dirt.dynamic = true
        dirt.scripted = true
        dirt.geometry = TRANSPARENT
    
        -- The internal script
        function dirt:created()
            e = self.entity
            self.base = scene:entity()
            self.base.parent = e
            self.base.position = vec3(0.5, 0.3, 0.5)
            local r = self.base:add(craft.renderer, craft.model.cube(vec3(2.8,0.6,2.8)))
            r.material = craft.material(asset.builtin.Materials.Specular)
            r.material.diffuse = color(133, 79, 30, 255)
            r.material.map = readImage(asset.builtin.Blocks.Brick_Grey)
    
            self.top = scene:entity()
            self.top.parent = e
            self.top.position = vec3(0.1, 0.6, 0.1)
            local r2 = self.top:add(craft.renderer, craft.model.cube(vec3(2.8,0.2,2.8), vec3(1.4,0.1,1.4)))
            -- local r2 = self.top:add(craft.renderer, craft.model(asset.builtin.Primitives.Monkey))
            r2.material = craft.material(asset.builtin.Materials.Specular)
            r2.material.diffuse = color(66, 47, 30, 255)
            r2.material.map = readImage(asset.n0)
            r2.material.normalMap = readImage(asset.n1)
            self.angle = 0
        end
    
        -- Because of using the craft standard model(craft.model.cube), here’s update()
        function dirt:update()
            self.top.rotation = quat.eulerAngles(0,  self.angle+ElapsedTime*100, 0)
        end
    
        return dirt
    end
    
    function newBlockTypeDirt()
        -- Create user-defined block type
        scene.voxels.blocks:addAssetPack("Blocks")
        local dirt = scene.voxels.blocks:new("myDirt")
        dirt.setTexture(ALL, "Blocks:Dirt")
        dirt.setColor(ALL, color(239, 222, 5))
        dirt.tinted = true
        dirt.scripted = true
        dirt.state:addFlag("on", false)
    
        -- The internal script
        function dirt:created()
            self:schedule(60)
            self:set(COLOR, color(108, 233, 80))
        end
    
        function dirt:blockUpdate()
            -- Randomise colour based on location
            -- local x,y,z = self:xyz()
            -- math.randomseed(x * y * z)
            local c =color(math.random(128,255), math.random(128,255), math.random(128,255))
            -- self.voxels:set(x,y,z,"color", c)
            self:set(COLOR, c)
            self:schedule(10)
        end
    
        return dirt
    end
    
    function update(dt)
        scene:update(dt)
    end
    
    function draw()
        update(DeltaTime)    
        scene:draw()
    end
    

    https://youtu.be/pY7MW9dS8F8

  • Posts: 239

    @dave1707

    15,000,000 voxel cubes before Codea crashed.

    really?? i can only get around 16K 2d meshes on the screen at 15-30fps,

    15 million is surprising

  • dave1707dave1707 Mod
    Posts: 9,808

    @binaryblues I don’t know about anyone else, but for me your examples are getting harder and harder to follow as they’re getting larger. It’s hard to figure out what code goes with what example is being drawn on the screen. Plus I’m seeing code that I can’t find anywhere in the document, for example, schedule() or code that doesn’t match the format of what’s in the document, set(COLOR,c). Maybe I’m just having trouble finding them in the documents.

  • dave1707dave1707 Mod
    Posts: 9,808

    @skar Here’s the code I was using drawing the cubes. I was able to do a cube(345) which gave me over a 15,000,000 cube count. I tried 350 and crashed. This code does cube(100) which is a cube 100x127x100. You can try cube() greater than 345 to see where you crash.

    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(100,80,0), 400, 0, 10000)    
        v.rx=-10
        v.ry=-30
    
        scene.voxels.blocks:addAssetPack("Blocks")   
        grass = scene.voxels.blocks:new("Table")
        grass.setTexture(ALL, "Blocks:Table")  
    
        scene.voxels.visibleRadius=90
        scene.voxels:resize(vec3(60,1,60))          
        scene.voxels.coordinates = vec3(0,0,0) 
    
        count=0
        cube(100)       -- 345 works, larger sizes crashes codea
    end
    
    function update(dt)
        scene:update(dt)
    end
    
    function draw()
        update(DeltaTime)
        scene:draw()
        text("Number of cubes drawn "..count,WIDTH/2,HEIGHT-50)
        text("memory "..collectgarbage("count"),WIDTH/2,HEIGHT-100)
        collectgarbage()
    end
    
    function cube(s)
        scene.voxels:fill("Table")  
        for x1=1,s do
            for y1=1,127 do
                for z1=1,s do
                    count=count+1 
                    scene.voxels:block((x1),(y1),(z1))
                end
            end
        end
    end
    
  • Posts: 190

    @dave1707 I also think that the sample code is getting longer and longer, and I’m thinking about removing some of the stuff that was in the previous example, and keeping it in case I have to repeat it, it’ll make user feel more familiar.You’re right that the full usage of these functions can not be found in the documentation. I gleaned this information from two places:

    That’s where I get confused. For example, in addElement () , I don’t know what these two parameters do:

    • collision = STEP
    • ao = false

    Because in the example code, they only appear once, closing them doesn’t seem to make any particular difference, and I don’t know if there are any other arguments in this function that aren’t listed in the sample program. We have the same problem.It’s like doing a jigsaw puzzle together. Thanks for your test code.

  • Posts: 190

    A condensed version of Example 6, which retains only what is used each time:

    viewer.mode = FULLSCREEN
    
    function setup()
        scene = craft.scene()
        scene.sky.material.sky = color(80, 203, 233)
        scene.sky.material.horizon = color(80, 108, 233)
    
        player = scene.camera:add(OrbitViewer, vec3( 40, 25, 40), 8, 1, 400)
    
        -- set voxel terrain parameters: size, coord
        scene.voxels:resize(vec3(5,1,5))      
        scene.voxels.coordinates = vec3(0,0,0)    
    
        -- Using default block type: SOLID as the filling unit
        scene.voxels:fill("solid")    
        -- Create a box using "Solid" block type, every unit in the box is a "solid" block
        scene.voxels:box(0,0,0, 16*8,10,16*8)
    
        -- Create a new block type "myDirtModel2", using addElement() to build model
        newBlockTypeDirtWithAddElement("myDirtModel2")
    
        -- Using new block type: myDirtModel2 as the filling unit
        scene.voxels:fill("myDirtModel2")
        -- A single block
        scene.voxels:block(vec3(30,20,35))
        -- Create a sphere and a line using "myDirtModel2" block type, 
        -- every unit in those two shapes is a "myDirtModel2" block
        scene.voxels:sphere(40,20,77,8)
        scene.voxels:line(10,20,0,10,50,30)
    
        -- craft.scene.main = scene
    end
    
    
    function newBlockTypeDirtWithAddElement(blockTypeName)
        scene.voxels.blocks:addAssetPack("Blocks")
    
        local dirt = scene.voxels.blocks:new(blockTypeName)    
        dirt.setTexture(ALL, "Blocks:Dirt")
        -- dirt.setColor(ALL, color(227, 89, 14))
        dirt.scripted = true
    
        -- custom model from state
        function dirt:buildModel(model)
            model:clear()
            model:addElement
            {
                lower = vec3(0,0,0),
                upper = vec3(255,80,255), 
                textures = "Blocks:Wood",   
                collision = STEP,        
                ao = false
            }
    
            model:addElement
            {
                lower = vec3(0,60,0),
                upper = vec3(156,156,190),  
                textures = "Blocks:Stone", 
                collision = STEP,   
                ao = false
            }  
    
            model:addElement
            {
                lower = vec3(0,0,0),
                upper = vec3(106,255,100),  
                textures = "Blocks:Dirt", 
                collision = STEP,   
                ao = false
            }  
        end
    
        return dirt
    end
    
    
    function update(dt)
        scene:update(dt)
    end
    
    function draw()
        update(DeltaTime)    
        scene:draw()
    end
    
  • dave1707dave1707 Mod
    Posts: 9,808

    @binaryblues I also looked thru Block Library but it still didn’t explain things. As for your examples, there’s a lot there to learn from. Maybe you can separate each of the different voxels into their own projects so it’s easier to see what you did for each one. I also noticed the 2 parameters that didn’t seem to do anything when I commented them out. I was thinking that they were going to be use for something in future examples but they never got around to using them.

  • dave1707dave1707 Mod
    Posts: 9,808

    @binaryblues Thanks for the link above. There’s quite a lot there. I’ll have to look thru it tomorrow. I’ll look at your latest example above tomorrow also.

  • Posts: 190

    Example7: Simple block type again

    To simplify the example, some simple unscripted block types are used several times in the follow-up, so the function that created the simple block types is overridden.

    This time, I used the newly created simple block type "simpleGrass" to re fill the ground so it wasn’t dark but Green.

    The code:

    viewer.mode = FULLSCREEN
    
    function setup()
        scene = craft.scene()
        scene.sky.material.sky = color(80, 203, 233)
        scene.sky.material.horizon = color(80, 108, 233)
    
        player = scene.camera:add(OrbitViewer, vec3( 40, 25, 40), 8, 1, 400)
    
        -- set voxel terrain parameters: size, coord
        scene.voxels:resize(vec3(5,1,5))      
        scene.voxels.coordinates = vec3(0,0,0)    
    
        -- Create a new block type "simpleGrass"
        createSimpleBlockType("simpleGrass", "Blocks:Grass Top", color(201, 233, 80))
        -- Using default block type: SOLID as the filling unit
        scene.voxels:fill("simpleGrass")    
        -- Create a box using "Solid" block type, every unit in the box is a "solid" block
        scene.voxels:box(0,0,0, 16*8,10,16*8)
    
        -- Create a new block type "simpleDirt1"
        createSimpleBlockType("simpleDirt1", "Blocks:Dirt", color(83, 80, 233))
    
        -- Using new block type: myDirtModel2 as the filling unit
        scene.voxels:fill("simpleDirt1")
        -- A single block
        scene.voxels:block(vec3(30,20,35))
        -- Create a sphere and a line using "simpleDirt1" block type, 
        -- every unit in those two shapes is a "simpleDirt1" block
        scene.voxels:sphere(40,20,77,8)
        scene.voxels:line(10,20,0,10,50,30)
    
        -- craft.scene.main = scene
    end
    
    
    function createSimpleBlockType(blockTypeName,texture,blockColor)
        -- Create user-defined block type
        scene.voxels.blocks:addAssetPack("Blocks")
    
        local dirt = scene.voxels.blocks:new(blockTypeName)
        dirt.setTexture(ALL, texture or "Blocks:Dirt")
        dirt.setColor(ALL, blockColor or color(239, 222, 5))
        dirt.tinted = false
    end
    
    
    function update(dt)
        scene:update(dt)
    end
    
    function draw()
        update(DeltaTime)    
        scene:draw()
    end
    
  • Posts: 190

    @dave1707 The built-in sample Block Library is well written, with some comments in place, but more needs to be done to analyze the code and see what it does line by line. I’m glad these examples are helpful, and your suggestion is exactly what I’m considering. I’ll introduce only one block type for each example in the future to make it easier for beginners to learn. These are things we’ve seen all the sample code can not figure out, and you may end up having to turn to the developer. In fact, the most help comes from the documentation provided by the developers.

    You are welcome. Don’t worry, it’s going to be a long term project, I’ll probably be around a lot in the near future, and we all share the goal of making voxels work.

  • Posts: 190

    To keep the sample code short and easy to read, but also to keep track of all the work I’ve done, I decided to publish it this way:

    • The posted code is the latest example, the newest, the simplest, the most essential parts can be copied, pasted and run independently.
    • The packaged ZIP project file contains all the content (the main tab is the pasted content).
  • Posts: 190

    Example 8: The procedural generation block type, it is composite block type.

    We first generate two kinds of simple block types:

    • simpleGrass
    • simpleDirt1

    and then use these two kinds of simple block types to generate tree block type.

    The code:

    viewer.mode = FULLSCREEN
    
    function setup()
        scene = craft.scene()
        scene.sky.material.sky = color(80, 203, 233)
        scene.sky.material.horizon = color(80, 108, 233)
    
        player = scene.camera:add(OrbitViewer, vec3( 40, 25, 40), 8, 1, 400)
    
        -- set voxel terrain parameters: size, coord
        scene.voxels:resize(vec3(5,1,5))      
        scene.voxels.coordinates = vec3(0,0,0)    
    
        -- Create 2 new block types: "simpleGrass", "simpleDirt1"
        createSimpleBlockType("simpleGrass", "Blocks:Grass Top", color(201, 233, 80))
        createSimpleBlockType("simpleDirt1", "Blocks:Dirt", color(83, 80, 233))
    
        -- Using block type: simpleGrass as the filling unit
        scene.voxels:fill("simpleGrass")    
        -- Create a box using "simpleGrass" block type, every unit in the box is a "simpleGrass" block
        scene.voxels:box(0,0,0, 16*8,10,16*8)
    
        -- Create a new block type "TreeGenerator", 
        -- This is a composite block type, based on two block type: "simpleGrass", "simpleDirt1"
        proceduralGenerateBlockType("TreeGenerator")
    
        -- Using new block type: TreeGenerator as the filling unit
        scene.voxels:fill("TreeGenerator")
        -- A single block
        scene.voxels:block(vec3(30,20,35))
        -- Create a sphere and a line using "TreeGenerator" block type, 
        -- every unit in those two shapes is a "TreeGenerator" block
        scene.voxels:line(10,20,0,10,30,40)
        scene.voxels:sphere(40,20,60,4)
        -- craft.scene.main = scene
    end
    
    
    function createSimpleBlockType(blockTypeName,texture,blockColor)
        -- Create user-defined block type
        scene.voxels.blocks:addAssetPack("Blocks")
    
        local dirt = scene.voxels.blocks:new(blockTypeName)
        dirt.setTexture(ALL, texture or "Blocks:Dirt")
        dirt.setColor(ALL, blockColor or color(239, 222, 5))
        dirt.tinted = false
    end
    
    
    function proceduralGenerateBlockType(blockTypeName)
        scene.voxels.blocks:addAssetPack("Blocks")
        local tree = scene.voxels.blocks:new(blockTypeName)
        tree.scripted = true
        -- tree.geometry = EMPTY -- Make generator block invisible
        tree.static.canDig = false
        tree.static.hasIcon = true
        tree.static.canPlace = true
    
        function tree:created()
            self:schedule(60)
        end
    
        function tree:blockUpdate(t)
            local x,y,z = self:xyz()
    
            -- Check is enough surrounding area has been loaded to generate
            if self.voxels:isRegionLoaded(x-3, y, z-3, x+3, y,z+3) then
                self:generate()
                -- If this fails then try again in a second
            else
                self:schedule(60)
            end
        end
    
        function tree:generate()
            local x,y,z = self:xyz()
    
            -- Base random seed on location of tree
            math.randomseed(x * y * z)
            local height = math.random(4,5)
            local size = math.floor(height/2)
            self.voxels:set(x,y,z,"empty")
    
            -- Trunk 
            -- Using block type "simpleDirt1" to fill trunk     
            self.voxels:set(x,y-1,z,"simpleDirt1")    
            self.voxels:fill("simpleDirt1")
            self.voxels:box(x,y,z,x,y+height,z)
    
            -- Leaves
            -- Using block type "simpleGrass" to fill Leaves     
            self.voxels:fill("simpleGrass")
            self.voxels:fillStyle(UNION)
            self.voxels:sphere(x,y+height,z,size)
        end
    end
    
    
    function update(dt)
        scene:update(dt)
    end
    
    function draw()
        update(DeltaTime)    
        scene:draw()
    end
    
  • dave1707dave1707 Mod
    edited January 14 Posts: 9,808

    @binaryblues Heres an example I posted before. Try the different ss values (3, 9, 27, 81, 243). Don’t know why 243 doesn’t work right. Not sure if its my code or the way voxels work.

    PS. I know how to draw Voxel blocks at x,y,z positions, but that’s about it. Your examples here are going to expand my Voxel knowledge.

    viewer.mode=FULLSCREEN
    
    function setup()
        ss=81       -- cube size, powers of 3 only (3, 9, 27, 81, 243)
        -- 243 doesnt draw right.
    
        fill(255)
        assert(OrbitViewer, "Please include Cameras as a dependency")
        scene = craft.scene() 
        v=scene.camera:add(OrbitViewer,vec3(ss,ss,ss), ss*3, 0, 6000)    
        v.rx=-10
        v.ry=-30
    
        scene.voxels.blocks:addAssetPack("Blocks")
        tab = scene.voxels.blocks:new("Table")
        tab.setTexture(ALL, "Blocks:Table") 
        scene.voxels:fill("Table")
    
        scene.voxels.visibleRadius=90
        scene.voxels:resize(vec3(60,1,60))          
        scene.voxels.coordinates = vec3(ss,ss,ss) 
        count,rec=0,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("Number of recursive calls "..rec,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
                            rec=rec+1
                            cube(x1+x,y1+y,z1+z,s)
                        else
                            count=count+1
                            scene.voxels:block((x1+x+ss),(y1+y+ss),(z1+z+ss))
                        end
                    end
                end            
            end
        end
    end   
    
  • edited January 14 Posts: 2,574

    @John @binaryblues - last two Voxel demos gave me an error when run, added dependency for cameras. @binaryblues -recommend you set up a template with cameras dependency included - a Craft template.

    Zooming in, to check for the earlier issues with crashing , fired up errors on both,
    Think this may be due to a different environment with the latest generation of Craft. Images attached.

    @binaryblues, demos are getting more interesting and more involved. Thanks.

    Edit: in the Craft environment can the camera traverse the central axis ? Seems a bit restricted.

  • edited January 16 Posts: 190

    @dave1707 I think I may have found the reason. Resize takes two parameters:

    • sizeInChunks: vec3(a,b,c)
    • chunkSize: vec3(d,e,f)

    It indicates that the maximum range of the generated terrain is:

    • vec3(a * d, b * e, c * f)

    Your code is:

    scene.voxels:resize(vec3(60,1,60))
    

    There are two default settings, the b in sizeInChunks is only 1, and the chunkSize using the default value:

    • vec3(16,128,16),

    So the maximum range of your terrain is vec3(60 * 16, 1 * 128, 60 * 16), if you want to expand the range of the y , you can only do that by setting parameter chunkSize, on My iPad, there are only so many settings that can be used to draw a quarter of the way to crash, and only a little bit bigger to run.

    This default looks odd,It’s not very intuitive.

    Here the maximum range is vec3(8 * 16, 1 * 128, 8 * 16)==vec3(128,128,128), You can get the 1st snapshot.

    scene.voxels:resize(vec3(8,1,8), vec3(16,128,16))       
    

    Here the maximum range is vec3(16 * 16, 1 * 256, 16 * 16)==vec3(256,256,256), You can get the 2nd snapshot.

    scene.voxels:resize(vec3(16,1,16), vec3(16,256,16))          
    

    That’s the limit without causing crash. Halfway done

    scene.voxels:resize(vec3(32,1,16), vec3(16,512,16))      
    

    https://youtu.be/dhbtDV09lf8

  • Posts: 190

    @Bri_G Thank you for your advice and for the time spent testing. I haven’t used the template very much, but I’ll try to include it in the next example program, in my environment, as long as there are a large number of complex block type (such as spheres with a larger radius) , crashes are common, causing me to have to reduce the size of the sphere, as soon as it’s finished, I click on the screen to rotate and zoom, and I lose touch, which means there’s nothing to do but click and rerun, this phenomenon can be repeated again and again, I wonder if you have encountered this problem?

  • edited January 14 Posts: 2,574
    @binaryblues - yes, occasionally. When you are in a voxel environment you tend to want to zoom around so camera mobility and zoom are important. Errors and crashes need to be resolved or at least explained.
  • Posts: 190

    @Bri_G Since many of the crash problems are due to a lack of lua memory, I was thinking that if I could run the collectgarbage() function in some places where complex blocks are heavily used, maybe the problem would improve. But sometimes it crashes at the first try, and there’s no good way to do that.

  • dave1707dave1707 Mod
    Posts: 9,808

    @binaryblues Thanks for the info. I was able to play around with the visibleRadius and resize values and managed to get the lower third of the cube to display. A radius of 8 is just enough to get the length and width of the cube to show. If I change the 218 for the height to a higher value, Codea crashes. But the 2 lines below doesn’t crash Codea and draws some of the cube.

    I’m not sure why I can display a straight cube with a size of 345x345x345 that doesn’t crash, but this cube with a size of 243x243x243 does.

    Guess I don’t understand voxels well enough yet.

        scene.voxels.visibleRadius=8
        scene.voxels:resize(vec3(16,1,16), vec3(24,218,24))          
    
  • Posts: 2,574
    @binaryblues - if there was some way of calculating scope, i.e. the visible extent of the scene on your pad, that could reduce processing power and memory allocation. Not sure how to approach that.
  • Posts: 190

    @dave1707 There should be a block limit, and I suspect there may be a pre determined maximum memory allocation for blocks. In the sample "Block Library" for modeling, a block can not be larger than vec3(255,255,255)voxels.

    • addElement()

      • lower >= vec3(0,0,0)
      • upper <= vec3(255,255,255)

    I guess it could be because of that limitation.
    Your question prompted me to take a hard look at the use of the resize() method, which I used to fill in the numbers by feeling. I, too, am on the road to learning voxels, Learn a little bit more every day.

    @Bri_G You mean LOD? In fact, I specifically kept the drawing size at the edge of the crash because it was more helpful in finding hidden problems. If you want a more stable example, you can scale it down a bit, like the thickness of the ground, the radius of the sphere can be reduced, and so on.

  • Posts: 2,574

    @John @binaryblues - just in case you didn't believe me - here's a crash video.

    Craft crash

  • edited January 15 Posts: 190

    @Bri_G I’m sure you’ve come across crash, which is so easy to trigger in recent beta versions, I recently came across two crash, one with this line:

    shader("D:a")
    

    or

    shader("Documents:a")
    

    The other is that I recently searched all the voxels related discussions in the forums and found a voxels system written by an early user that would crash in a few seconds.I’m gonna clean it up and put it up. I tried to read the code to locate the problem, but I couldn’t figure out why the crash happened

    Here is the early voxels propotype:

  • Posts: 327
    @skar Are those 16K meshes separate Mesh objects?

    If so, the number of draw() calls is probably your bottleneck there. I'd imagine craft.voxels lowers the number of OpenGL draw calls drastically to something manageable and more performant.

    Fwiw, the overhead of draw calls in OpenGL is one of the main driving forces for the creation of newer graphics APIs like Metal & Vulkan.
  • edited January 15 Posts: 190

    Example9: More personalized simple block type

    New chages:

    • You can set the texture map and the color on each side, using the code like:
    dirt.setTexture(UP, "Blocks:Dirt")
    dirt.setTexture(DOWN, "Blocks:Stone")
    dirt.setTexture(EAST, "Blocks:Grass2")
    dirt.setTexture(NORTH, "Blocks:Grass1")
    dirt.setTexture(WEST, "Blocks:Leaves")
    dirt.setTexture(SOUTH, "Blocks:Oven")
    
    dirt.setColor(UP, color(255))
    ...
    dirt.setColor(SOUTH, color(255))
    
    • Added a box with a maximum of 255 * 255 * 255 so you can locate coord

    @John I found two problems:

    • NORTH will use the same texture map as SOUTH, It’s not working on its own.

    • The tinted switch works the other way around. When I set it to true, the block will go dark.

    The code:

    viewer.mode = FULLSCREEN
    
    function setup()
        scene = craft.scene()
        scene.sky.material.sky = color(80, 203, 233)
        scene.sky.material.horizon = color(80, 108, 233)
    
        player = scene.camera:add(OrbitViewer, vec3( 40, 25, 40), 8, 1, 4000)
    
        -- set voxel terrain parameters: size, coord
        scene.voxels:resize(vec3(5,1,5),vec3(16,128,16))      
        scene.voxels.coordinates = vec3(0,0,0)    
    
        -- Create 2 new block types: "simpleGrass", "simpleDirt1"
        createSimpleBlockType("simpleGrass", "Blocks:Grass Top", color(201, 233, 80))
    
        -- Using block type: simpleGrass as the filling unit
        scene.voxels:fill("simpleGrass")    
        -- Create a box using "simpleGrass" block type, every unit in the box is a "simpleGrass" block
        scene.voxels:box(0,0,0, 16*8,10,16*8)
    
        -- Using new block type: TreeGenerator as the filling unit
        scene.voxels:fill("simpleGrass")
        -- A single block
        scene.voxels:block(vec3(30,25,35))
        -- Create a sphere and a line using "simpleGrass" block type, 
        -- every unit in those two shapes is a "simpleGrass" block
        scene.voxels:line(10,20,0,10,30,40)
        scene.voxels:sphere(40,20,60,4)
        -- craft.scene.main = scene
    end
    
    
    function createSimpleBlockType(blockTypeName,texture,blockColor)
        -- Create user-defined block type
        scene.voxels.blocks:addAssetPack("Blocks")
    
        local dirt = scene.voxels.blocks:new(blockTypeName)
        ---[[
        dirt.setTexture(ALL, texture or "Blocks:Dirt")
        dirt.setTexture(UP, "Blocks:Dirt")
        dirt.setTexture(DOWN, "Blocks:Stone")
        dirt.setTexture(EAST, "Blocks:Grass2")
        dirt.setTexture(NORTH, "Blocks:Grass1")
        dirt.setTexture(WEST, "Blocks:Leaves")
        dirt.setTexture(SOUTH, "Blocks:Oven")
        --]]
    
        ---[[
        dirt.setColor(ALL, blockColor or color(251))
        dirt.setColor(UP, color(255))
        dirt.setColor(DOWN, color(238, 235, 235))
        dirt.setColor(EAST, color(5, 235, 239))
        dirt.setColor(NORTH, color(249, 248, 248))
        dirt.setColor(WEST, color(249))
        dirt.setColor(SOUTH, color(255))
        --]]
    
        dirt.tinted = false
    end
    
    function update(dt)
        scene:update(dt)
        blockRange()
    end
    
    function draw()
        update(DeltaTime)    
        scene:draw()
    end
    
    -- Draw a 256*256*256 box, from vec3(0,0,0) to vec3(255,255,255), it is the block type range.
    function blockRange()
        scene.debug:line(vec3(0, 0, 0),vec3(255, 0, 0),color(47, 239, 5))
        scene.debug:line(vec3(0,0,0),vec3(0, 255, 0),color(239, 5, 5))
        scene.debug:line(vec3(0,0,0),vec3(0, 0, 255),color(5, 41, 239))
    
        scene.debug:line(vec3(255,255,255),vec3(0, 255, 255),color(239, 91, 5))
        scene.debug:line(vec3(255,255,255),vec3(255, 0, 255),color(214, 5, 239))
        scene.debug:line(vec3(255,255,255),vec3(255, 255, 0),color(5, 238, 239))
    
        scene.debug:line(vec3(255, 255, 0),vec3(255, 0, 0),color(239, 234, 5))
        scene.debug:line(vec3(255,0,255),vec3(255, 0, 0),color(239, 5, 5))
        scene.debug:line(vec3(0,0,255),vec3(255, 0, 255),color(128, 5, 239))
    
        scene.debug:line(vec3(0,255,255),vec3(0, 0, 255),color(239, 5, 172))
        scene.debug:line(vec3(0,255,255),vec3(0, 255, 0),color(185, 239, 5))
        scene.debug:line(vec3(255,255,0),vec3(0, 255, 0),color(5, 238, 239))
    end
    

    https://youtu.be/XrQn8YV3UpE

  • Posts: 190

    @Bri_G I used the template this time, but I don’t know if it will work.

  • Posts: 2,574

    @binaryblues - nice demo, scrolled around all over the model, including stepping out of the box and no crashing. Thanks.

  • Posts: 190

    @Bri_G OK, thank you for the test. I have to think about how I’m going to prepare the next example, the previous example block is all about appearance, and then there’s the interaction, which is a little bit more complicated

  • Posts: 190

    @Bri_G OK, thank you for the test. I have to think about how I’m going to prepare the next example, the previous example block is all about appearance, and then there’s the interaction, which is a little bit more complicated

  • Posts: 190

    Example10: Details on using the tinted switch

    After a lot of research, finally understand the details of the use of the tinted switch. It must be used with the built-in script, where the color is set using statements like this:

        dirt.tinted = true
    
        function dirt:created()
            local x,y,z = self:xyz()       
            self.voxels:set(x,y,z,"color", color(128,128,128,255))
        end
    

    Then we have to face the problem that if a simple unscripted block sets the tinted switch to true, it doesn’t take into account the block’s original color, which is the color set by this statement:

        dirt.setColor(UP, color(255))
    

    it’s gonna turn black.

    I found a way around this by traversing the entire coordinate area and using tinted color for all the blocks in that coordinate area, mainly using this method:

        - The coordinate area is from vec3(0,0,0) to vec3(40,20,128)
        scene.voxels:iterateBounds(0,0,0,40,20,128,  function(x,y,z)
            scene.voxels:set(x,y,z,"color",color(240, 242, 10))
        end)
    

    This is a global setting, because the simple block does not provide a built-in script, so it can not be set by itself, only in external settings, the benefit is to save a lot of resources.

    I call them global tinted settings and local tinted settings, respectively, and the example code demonstrates what happens when you use both settings together. Note that I’m only putting local tinted settings in function created() in built-in script, you can try to put it in the blockUpdate(), or you can try to put it in the update() function when the global setting is now in setup()

    The code:

    viewer.mode = FULLSCREEN
    
    function setup()
        scene = craft.scene()
        -- scene.sky.material.sky = color(80, 203, 233)
        -- scene.sky.material.horizon = color(80, 108, 233)
    
        player = scene.camera:add(OrbitViewer, vec3( 40, 25, 40), 8, 1, 4000)
        c = scene.camera:get(craft.camera)
        c.farPlane = 5000
    
        -- set voxel terrain parameters: size, coord
        scene.voxels:resize(vec3(16,1,16),vec3(64,512,64))      
        scene.voxels.coordinates = vec3(0,1000,0)    
        scene.voxels.visibleRadius=1000
    
        -- Create 2 new block types: "simpleGrass", "simpleDirt1"
        createSimpleBlockType("simpleGrass", "Blocks:Grass Top", color(201, 233, 80))
    
        -- Using block type: simpleGrass as the filling unit
        scene.voxels:fill("simpleGrass")    
        -- Create 2 boxes using "simpleGrass" block type, every unit in the box is a "simpleGrass" block
        scene.voxels:box(0,0,0, 16*4,1,16*8)
    
        scene.voxels:box(0,2,0, 8,255,8)
    
        -- Using new block type: simpleGrass as the filling unit
        scene.voxels:fill("simpleGrass")
        -- A single block
        scene.voxels:block(vec3(30,25,35))
        -- Create a sphere and a line using "simpleGrass" block type, 
        -- every unit in those two shapes is a "simpleGrass" block
        scene.voxels:line(10,20,0,10,30,40)
        scene.voxels:sphere(40,20,60,10)
        -- craft.scene.main = scene
    
        -- Iterate over the block at each location within the region and set its tinted color
        scene.voxels:iterateBounds(0,0,0,40,20,128,  function(x,y,z)
            scene.voxels:set(x,y,z,"color",color(240, 242, 10))
        end)   
    end
    
    
    function createSimpleBlockType(blockTypeName,texture,blockColor)
        -- Create user-defined block type
        scene.voxels.blocks:addAssetPack("Blocks")
    
        local dirt = scene.voxels.blocks:new(blockTypeName)
        ---[[
        dirt.setTexture(ALL, texture or "Blocks:Dirt")
        dirt.setTexture(UP, "Blocks:Dirt")
        dirt.setTexture(DOWN, "Blocks:Stone")
        dirt.setTexture(EAST, "Blocks:Grass2")
        dirt.setTexture(NORTH, "Blocks:Grass1")
        dirt.setTexture(WEST, "Blocks:Leaves")
        dirt.setTexture(SOUTH, "Blocks:Oven")
        --]]
    
        ---[[
        dirt.setColor(ALL, blockColor or color(251))
        dirt.setColor(UP, color(255))
        dirt.setColor(DOWN, color(238, 235, 235))
        dirt.setColor(EAST, color(5, 235, 239))
        dirt.setColor(NORTH, color(249, 248, 248))
        dirt.setColor(WEST, color(249))
        dirt.setColor(SOUTH, color(255))
        --]]
    
        dirt.tinted = true
        dirt.scripted = true
        dirt.state:addFlag("on", false)
    
        function dirt:created()
            -- Randomise colour based on location
            local x,y,z = self:xyz()
            math.randomseed(x * y * z)
            local c =color(math.random(128,255), math.random(128,255), math.random(128,255))
            self.voxels:set(x,y,z,"color", c)
        end
    end
    
    function update(dt)
        scene:update(dt)
        blockRange()
    end
    
    function draw()
        update(DeltaTime)    
        scene:draw()
    end
    

    https://youtu.be/3Bm-CP-EP0o

Sign In or Register to comment.