3D Cube Not Getting Drawn

Hello Everyone!
Today I learned how to make 3D meshes and stuff thanks to Ignatz’s really cool ebook! I tested my skills by writing my own “Rectangular Prism” class, and it worked! I then wanted a ground, so I used Ignatz’s “Tile” class that tiles a 3D mesh with the image you give it. Unfortunately, tough, when I put Ground.mesh:draw() in the draw function next to Block.mesh:draw(), my block stopped showing! I assume it has something to do with the Tiles class since everytime I comment out Ground.mesh:draw(), my block is visible again. I don’t know how shaders work (that’s for me to learn some other day), but I’m guessing Tile’s shader may be causing the problem?

Here is the code:

-- Use this function to perform your initial setup
function setup()
    BlockPos = vec3(0,200,-50)
    BlockSpeed = 7
    BlockXRot = 2
    BlockYRot = 0
    Block = RectangularPrism({x = BlockPos.x, y = BlockPos.y, z = BlockPos.z, w = 100, h = 100, d = 100})
    Ground = Tile(readImage("Cargo Bot:Game Area"),1)
    Ground:AddSurface(vec3(-1200,0,-1200),vec3(1200,0,1200))

    Block.mesh.texture = readImage("Platformer Art:Crate") -- Tap this blue bubble to change the texture.
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)
    
    Block.pos.x = Block.pos.x + BlockSpeed
    Block.rotation.x = Block.rotation.x + BlockXRot
    Block.rotation.y = Block.rotation.y + BlockYRot
    if Block.pos.x < -1000 or Block.pos.x > 1000 then
        BlockSpeed = -BlockSpeed
        BlockXRot = -BlockXRot
        BlockYRot = -BlockYRot
    end
    
    perspective()
    camera(0,300,-300,Block.pos.x,Block.pos.y,Block.pos.z)
    
    Ground.mesh:draw() -- If I comment this out, it shows the cube?!
    
    Block:draw()
end

RectangularPrism = class()
function RectangularPrism:init(data)
    self.pos = vec3()
    self.pos.x = data.x
    self.pos.y = data.y
    self.pos.z = data.z
    self.w = data.w
    self.h = data.h
    self.d = data.d
    self.rotation = vec3()
    
    self.mesh = mesh()
    
    do -- A do loop because we won't be needing these local variables later on in this function.
        
        -- Below, we are setting up a few variables that will be needed a lot.
        local hlfW = self.w*0.5 -- the width will be along the x axis,
        local hlfH = self.h*0.5 -- the height will be along the y axis,
        local hlfD = self.d*0.5 -- and the depth will be along the z axis.
        
        -- We'll assume North is positive X, East is positive Z, South is negative X and West is negative Z,
        -- to make things easier to understand.
        -- Below, we are setting variables that define the corners in a rectangular prism.
        local topNorthWest = vec3(hlfW, hlfH, -hlfD)
        local topNorthEast = vec3(hlfW, hlfH, hlfD)
        local bottomNorthWest = vec3(hlfW, -hlfH, -hlfD)
        local bottomNorthEast = vec3(hlfW, -hlfH, hlfD)
        
        -- The southern side of the rectangular prism will have the same corners except their x axis will be negative.
        local topSouthWest = vec3(-hlfW, hlfH, -hlfD)
        local topSouthEast = vec3(-hlfW, hlfH, hlfD)
        local bottomSouthWest = vec3(-hlfW, -hlfH, -hlfD)
        local bottomSouthEast = vec3(-hlfW, -hlfH, hlfD)
        
        -- Now that we know all 8 corners in our prism, it should be easy to set the mesh vertices.
        
        -- Below, we are setting the vertices for the mesh.
        self.mesh.vertices = {
        topNorthWest,topNorthEast,topSouthWest,-- triangle 1 on top
        topNorthEast,topSouthWest,topSouthEast,-- triangle 2 on top
        bottomNorthWest,bottomNorthEast,bottomSouthWest,-- triangle 1 on bottom
        bottomNorthEast,bottomSouthWest,bottomSouthEast,-- triangle 2 on bottom
        bottomNorthWest,bottomNorthEast,topNorthWest,-- bottom triangle to North
        bottomNorthEast,topNorthWest,topNorthEast,-- top triangle to North
        bottomNorthEast,bottomSouthEast,topNorthEast,-- bottom triangle to East
        bottomSouthEast,topNorthEast,topSouthEast,-- top triangle to East
        bottomSouthWest,bottomSouthEast,topSouthWest,-- bottom triangle to South
        bottomSouthEast,topSouthWest,topSouthEast,-- top triangle to South
        bottomNorthWest,bottomSouthWest,topNorthWest,-- bottom triangle to West
        bottomSouthWest,topNorthWest,topSouthWest,-- top triangle to West
        }
    end
    
    -- Below we set some variables for the texture coordinates.
    local topLeft = vec2(0,1)
    local topRight = vec2(1,1)
    local bottomLeft = vec2(0,0)
    local bottomRight = vec2(1,0)
    
    -- Below, we are setting the texture coordinates.
    self.mesh.texCoords = {
    topLeft,topRight,bottomLeft, -- triangle 1 on top
    topRight,bottomLeft,bottomRight, -- triangle 2 on top
    topLeft,topRight,bottomLeft, -- triangle 1 on bottom
    topRight,bottomLeft,bottomRight, -- triangle 2 on bottom
    bottomLeft,bottomRight,topLeft, -- bottom triangle to North
    bottomRight,topLeft,topRight, -- top triangle to North
    bottomRight,bottomLeft,topRight, -- bottom triangle to East
    bottomLeft,topRight,topLeft, -- top triangle to East
    bottomRight,bottomLeft,topRight, -- bottom triangle to South
    bottomLeft,topRight,topLeft, -- top triangle to South
    bottomLeft,bottomRight,topLeft, -- bottom triangle to West
    bottomRight,topLeft,topRight -- top triangle to West
    }
    
end

function RectangularPrism:draw()
    pushMatrix()
    
    translate(self.pos.x,self.pos.y,self.pos.z)
    rotate(self.rotation.x, 1, 0, 0)
    rotate(self.rotation.y, 0, 1, 0)
    rotate(self.rotation.z, 0, 0, 1)
    
    self.mesh:draw()
    
    popMatrix()
end

-- Thank you so much Ignatz for the fantastic library below!

--This class tiles an image across a rectangle of any size and provides a mesh
--You can add as many rectangles as you like to the same mesh
--Each rectangle must be vertical or horizontal, not at an angle, ie floor, roof or walls
Tile=class()

--img = image name or the image itself
--s = scale of image (0.5 reduces by half, 2 doubles its size,
function Tile:init(img,s)
    if type(img)=="text" then img=readImage(img) end
    self.img=img
    self.iw,self.ih=img.width,img.height
    self.mesh=mesh()
    self.mesh.texture=self.img
    self.mesh.shader=shader(Tile.Shader.vertexShader,Tile.Shader.fragmentShader)
    self.scale=s
    self.v,self.t={},{}
end

--The parameters are as follows
--p1 = vec3(x,y,z) = a corner position 
--p2 = vec3(x,y,z) = the diagonally opposite corner position 
--s = scale of image (0.5 reduces by half, 2 doubles its size, default is what was provided in the init function)
function Tile:AddSurface(p1,p2,s)
    s=s or self.scale
    local w,h=self.img.width*s,self.img.height*s
    local d=p2-p1
    local v,t
    if d.x==0 then 
        v={vec3(p1.x,p1.y,p1.z),vec3(p1.x,p1.y,p2.z),vec3(p1.x,p2.y,p2.z),vec3(p1.x,p2.y,p1.z)}
        t={vec2(0,0),vec2(d.z/w,0),vec2(d.z/w,d.y/h),vec2(0,d.y/h)}
    elseif d.y==0 then 
        v={vec3(p1.x,p1.y,p1.z),vec3(p2.x,p1.y,p1.z),vec3(p2.x,p1.y,p2.z),vec3(p1.x,p1.y,p2.z)}
        t={vec2(0,0),vec2(d.x/w,0),vec2(d.x/w,d.z/h),vec2(0,d.z/h)}
    elseif d.z==0 then 
        v={vec3(p1.x,p1.y,p1.z),vec3(p2.x,p1.y,p1.z),vec3(p2.x,p2.y,p1.z),vec3(p1.x,p2.y,p1.z)}
        t={vec2(0,0),vec2(d.x/w,0),vec2(d.x/w,d.y/h),vec2(0,d.y/h)}       
    else return nil
    end
    local seq={1,2,3,3,4,1}
    for i=1,6 do
        table.insert(self.v,v[seq[i]])
        table.insert(self.t,t[seq[i]])
    end  
    self.mesh.vertices=self.v
    self.mesh.texCoords=self.t  
end

Tile.Shader = {
vertexShader = [[

uniform mat4 modelViewProjection;
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;

void main()
{
    vColor = color;
    vTexCoord = texCoord;
    gl_Position = modelViewProjection * position;
}

]],
fragmentShader = [[

precision highp float;
uniform lowp sampler2D texture;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;

void main()
{
    lowp vec4 col = texture2D( texture, vec2(mod(vTexCoord.x,1.0), mod(vTexCoord.y,1.0)));
    gl_FragColor = col;
}

]]}

BTW, for anyone that wants an easy way to make a 3D Rectangle, you may use my class “RectangularPrism” found in the code above.

And also, @Ignatz , thank you so much for writing that tutorial! :slight_smile:

I’m glad someone found the tutorial useful!

The code works fine for me - what iPad and iOS version do you have?

Works fine for me also. I’m on an iPad Air.

I have IOS 9.3.4 on my Ipad mini. But I think the problem is that I only have Scratchpad

Time to upgrade to the full version.

Oh, I would really love to upgrade! I’ve been wanting to since I got scratchpad, but I can’t, because I’m not allowed to buy things :frowning: . But, I’ll make the best of it until I am allowed.