Is this a bug in meshes?

I was going to explore the noise function, starting from @Simeon 's example. I first tried to replace the rectangles with meshes to speed up the program, and use higher resolutions. The problem is that some meshes are messed up, the x coordinate of one of the points is 0 when it hasn’t to be 0.

At first it seemed a random problem, but further exploration revealed that the broken meshes where not random, but 500, 1000, 2000, 4000. I haven’t looked further but there is a clear pattern.

I haven’t found any mistakes in the program, so I imagine there is some kind of error in the creation of rectangular meshes (I imagine they are just 2 adjacent triangular meshes).

http://www.youtube.com/watch?v=PO5Tx8HDoGI


supportedOrientations(LANDSCAPE_ANY)

tileSize = WIDTH/65
noiseScale = 1/5
noisePos = vec2(0,0)
noiseSpeed = 0.2

-- Use this function to perform your initial setup
function setup()
    parameter("noiseScale", 1/30, 1, 1/5)    
    parameter("noiseSpeed", 0.05, 1, 0.2)

    tiles = {}
    for x = 1, WIDTH/tileSize do
        tiles[x] = {}
        for y = 1, HEIGHT/tileSize do
            tiles[x][y] = noise(x * noiseScale, y * noiseScale)
        end
    end
end

function moveNoise()
    for x,column in ipairs(tiles) do
        for y,value in ipairs(column) do
            tiles[x][y] = math.floor((noise(x * noiseScale + noisePos.x, y * noiseScale + noisePos.y) + 1)*127)
        end
    end
end

-- This function gets called once every frame
function draw()
    background(231, 14, 14, 255)
    
    noStroke()
    noSmooth()
    spriteMode(CORNER)

    m = mesh()
    t = image(1,1)
    t:set(1,1,255,255,255)
    m.texture = t
    translate(tileSize/2,tileSize/2)
    local counter = 0
    for x,column in ipairs(tiles) do
        for y,value in ipairs(column) do
            local i = m:addRect((x-1)*tileSize, (y-1)*tileSize, tileSize-1, tileSize-1)
            m:setRectColor(i, color(value,value,value,255))
        end
    end
    m:draw()
    m:clear()
    noisePos = noisePos + vec2(0.5,0.3) * noiseSpeed
    moveNoise()
end

I ran into this also. If I create 500 rects with a mesh, everything seems fine. If I create 501 rects, then the verts of the 500th one are hosed. Here is a simple test case that reproduces the bug:


function setup()
    myMesh = mesh()
    myMesh.texture = "Tyrian Remastered:Blimp Boss"
    local w, h = spriteSize(myMesh.texture)
    
    for i = 1, 499 do
        myMesh:addRect(w, h, w/2, h/2)
    end

    --this one is messed up if I add one or more after this
    myMesh:addRect(WIDTH/2, HEIGHT/2, w/2, h/2)

    --comment this one out, and the problem doesn't manifest
    myMesh:addRect(WIDTH/2, HEIGHT/2 - 100, w/2, h/2)    
end

function draw()
    background(0)
    myMesh:draw()
end

Yes, it’s exactely the same problem.

I’m going to guess that the mesh system uses 500-slot long tables of some kind and skips the zero?
Perhaps make it so that the mesh function counts how many times it has run, and draws a blank mesh on every (n=a+1) Nth?

It sounds like a good workaround, @KMEB.

I’m pretty sure that I’ve come across this and discussed it on the forum with Simeon somewhere, but I can’t locate it right now.

The tables are actually 3000 because a rectangle consists of six vertices (it is decomposed into two triangles). The solution - if I’m remembering it right - is to assign an empty table to the mesh vertices first. This initialises everything correctly. So put in a mesh.vertices = {} at the start and see if that helps.

If not, I’ll have another go at tracking down the old discussion - I also thought that Simeon had fixed this but maybe it didn’t make it into the release.

@Andrew_Stacey, I’ve just tried it and the problem persists. Thank you anyways.

Ah, then that was due to a different bug which has been fixed. Sorry.

Nonetheless, I have come across this before. I’ll scan through my code to see where I have Really Big Meshes and see if I can find anything relevant.

In the meantime, I’ve already tried @KMEB 's workaround, and it works well. Thanks, KMEB.

Found it: http://www.twolivesleft.com/Codea/Talk/discussion/comment/7579#Comment_7579 See my comment at the end of my code. My workaround looks pretty similar to KMEB’s.

My solution was very similar, Andrew, only I lose less meshes, but yours is shorter :smiley: .

            counter = counter + 1
            if(counter == 500 or counter == 1000 or counter == 2000 or counter == 4000) then 
                counter = counter - 1
                m:addRect(0,0,0,0)
            end

I have created a new issue for this:
https://bitbucket.org/TwoLivesLeft/codea/issue/144/adding-more-than-500-rects-to-a-mesh-hoses

Thanks everyone for discovering this issue. I’ll look into what’s causing it shortly.

Thanks again, this bug has been fixed. It occurred when the mesh buffer resized dynamically to accommodate more vertices — it was erasing the last element each time it doubled capacity.

It will be fixed after version 1.4.1 (that one is still awaiting approval).

Thank you so much, @Simeon.

Yes, many thanks!

@Simeon, I also ran into this bug, with my recent experimentation with meshes (prompted by @Vega’s tutorial). Will you be publishing a roadmap for Codea after version 1.4.1?

@mpilgrem I will publish a roadmap for what will likely be 1.4.2.

I suggest another possible interim solution for the bug. It uses the resize() function associated with the mesh userdata (that is not documented in the in-app reference):


myBigMesh = mesh()
-- Before any rectangles are added to the mesh:
myBigMesh:resize(24000) -- Reset the maximum size of the buffer

(Update) Looking at the Codea Runtime Library, I see that this works at the (probably not insignificant) ‘cost’ of having a mesh that then starts with 24,000 empty (0,0,0) vertices…