Can a polygon's vertices be accessed after creation?

Another recent thread brought up an issue about how certain information for some display objects is still accessible after creating them, such as the radius of a circle or the path of a rect, but I was wondering if a polygon’s vertices are still somehow stored and accessible after the display object has been created?

I added some texture stuff that landed in a recent build. One of these is like a texture-based cousin of contentBounds and I wanted it for some shaders, e.g. when I needed 0-1 coordinates on a sprite frame. I added another property called textureVertices because it basically came for free when calculating the bounds.

The tests / example with my PR:

--- Frame test. -- -- Permission is hereby granted, free of charge, to any person obtaining -- a copy of this software and associated documentation files (the -- "Software"), to deal in the Software without restriction, including -- without limitation the rights to use, copy, modify, merge, publish, -- distribute, sublicense, and/or sell copies of the Software, and to -- permit persons to whom the Software is furnished to do so, subject to -- the following conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -- -- [MIT license: http://www.opensource.org/licenses/mit-license.php] -- print("# of available vertex texture units:", system.getInfo("maxVertexTextureUnits")) print("") local tex = graphics.newTexture{ type = "canvas", width = 128, height = 128 } local back = display.newRect(0, 0, 128, 128) back:setFillColor(1, 0, 0) local rect = display.newRect(0, 0, 32, 64) rect:setFillColor(0, 0, 1) tex:draw(back) tex:draw(rect) tex:invalidate() local fill = { type = "image", filename = tex.filename, baseDir = tex.baseDir } local function Bounds (object) local bounds = object.path.textureBounds return "Bounds: uMin = " .. bounds.uMin .. ", vMin = " .. bounds.vMin .. ", uMax = " .. bounds.uMax .. ", vMax = " .. bounds.vMax end local function Vertices (object) local vertices, t = object.path.textureVertices, {} for i = 1, #vertices, 2 do t[#t + 1] = "\t(" .. vertices[i] .. ", " .. vertices[i + 1] .. ")" end return "Vertices:\n" .. table.concat(t, "\n") end local vanilla = display.newRect(50, 50, 30, 30) vanilla.fill = fill print("VANILLA RECT") print(Bounds(vanilla)) print(Vertices(vanilla)) print("") local polygon = display.newPolygon(150, 120, { 0, -110, 27, -35, 105, -35, 43, 16, 65, 90, 0, 45, -65, 90, -43, 15, -105, -35, -27, -35, }) polygon.fill = fill print("STAR POLYGON") print(Bounds(polygon)) print(Vertices(polygon)) print("") local mesh = display.newMesh{ x = 300, y = 100, mode = "triangles", vertices = { -5, 0, 90, 0, 0, 100, 0, 100, 90, 0, 130, 100, 130, 100, 90, 0, 100, 0 }, uvs = { 0, 0, 0.25, 0, 0, .9, 0, .9, 0.25, 0, 1, .75, 1, .75, 0.25, 0, 1, 0 } } mesh:translate(mesh.path:getVertexOffset()) -- Translate mesh so that vertices have proper world coordinates mesh.fill = fill print("MESH") print(Bounds(mesh)) print(Vertices(mesh)) print("") local options = { frames = { { x = 64 - 16, y = 64 - 32, width = 32, height = 64 } } } local sheet = graphics.newImageSheet(tex.filename, tex.baseDir, options) local image = display.newImage(sheet, 1) image.x, image.y = 500, 100 print("SHEET-BASED IMAGE") print(Bounds(image)) print(Vertices(image)) print("") local sprite = display.newSprite(sheet, { name = "state", start = 1, count = 1 }) sprite.x, sprite.y = 600, 150 print("SPRITE FRAME") print(Bounds(sprite)) print(Vertices(sprite))

If I’m remembering correctly (and really, just from observation), the texture coordinates for anything other than meshes and sprites will be the normalized (0-1) coordinates based on the object’s content bounds. So in theory you could take the texture vertices here and apply them in reverse.

I just downloaded the newest daily build and tried your textureVertices. I must admit, that’s awesome!

It’s been a while since I worked with normalized vectors, so my memory is a bit hazy, but isn’t it impossible to reverse the normalization without knowing where the vertices start and how long each vector is?

For instance, if we take the star shape vertices from Corona docs for newPolygon, we start with:

vertices = { 0,-110, 27,-35, 105,-35, 43,16, 65,90, 0,45, -65,90, -43,15, -105,-35, -27,-35 } -- From where we get the values for the normalized vectors (rounded values to save space). normalized = { 0.37, 0.38, 0.5, 0, 0.63, 0.38, 0.63, 0.38, 1, 0.38, 0.7, 0.63, 0.7, 0.63, 0.81, 1, 0.5, 0.77, 0.5, 0.77, 0.19, 1, 0.3, 0.63, 0.3, 0.63, 0, 0.38, 0.37, 0.38, 0.37, 0.38, 0.63, 0.38, 0.7, 0.63, 0.7, 0.63, 0.5, 0.77, 0.3, 0.63, 0.3, 0.63, 0.37, 0.38, 0.7, 0.63 }

But, since all we know are the content bounds as well as the object’s x and y coordinates, that shouldn’t be enough to reverse the process, or am I forgetting about something?

At times like these, I really wish I still remembered some C++ so I could just go code in this feature to Corona myself. Perhaps I should pick up a book, this level of feature shouldn’t be too much.

Just in case there’s any confusion, by normalized I just mean between values between 0 and 1, as opposed to integer offsets as you’d see in sprite sheets, say. No unit vectors here.  :slight_smile:

I believe going from xMin , yMin (0, 0) to xMax , yMax (1, 1), as supplied by the  contentBounds , will get you the content coordinates. It’s kind of noisy, but the results were (again, if I’m remembering right) basically a stream like { x1, y1, x2, y2, x3, y3 … }, but three at a time like that (triangles), so sort of like the somewhat redundant input a non-indexed mesh would take.

I seem to have indeed misunderstood what you said. Serves me right for waking up at 5:30 to read about math and programming! :smiley:

I was able to get the vertices with your advice with the following code. Now I just need to figure out how to get rid of said triangles and merge them back into the original shape… but I’ll do that after I’ve had some tea and breakfast. :smiley:

local star = display.newPolygon( display.contentCenterX, display.contentCenterY, { 0,-110, 27,-35, 105,-35, 43,16, 65,90, 0,45, -65,90, -43,15, -105,-35, -27,-35 } ) star.alpha = 0.5 local vertices = { unpack( star.path.textureVertices ) } for i = 1, #vertices, 2 do vertices[i] = vertices[i]\*star.width vertices[i+1] = vertices[i+1]\*star.height end for i = 1, #vertices, 2 do display.newLine( star.contentBounds.xMin+vertices[i], star.contentBounds.yMin+vertices[i+1], vertices[i+2] and star.contentBounds.xMin+vertices[i+2] or star.contentBounds.xMin+vertices[1], vertices[i+3] and star.contentBounds.yMin+vertices[i+3] or star.contentBounds.yMin+vertices[2] ) end

Well, never mind breakfast. I may have figured this out before I got to the kitchen.

The above scenario can be solved by adding this bit of code to it.

local verticesNew = {} local overlap = false for i = 1, #vertices, 2 do for j = 1, #verticesNew, 2 do if vertices[i] == verticesNew[j] and vertices[i+1] == verticesNew[j+1] then overlap = true break end end if not overlap then verticesNew[#verticesNew+1] = vertices[i] verticesNew[#verticesNew+1] = vertices[i+1] end overlap = false end local starNew = display.newPolygon( 240, 160, verticesNew )

i.e. just checking if a vertex already exists and disregard it if it does. This leads me to the question of how did you program this? Can I assume that this kind of solution will always be valid, or should I slice the vertices into numerous polygons (namely to said triangles) and then apply polygon union on them? This is really just a question of using a lightweight or a heavyweight algorithm, I have both ready to go.

Sounds valid to me.

If you want to see the details, the whole PR is actually fairly small, so shouldn’t be overwhelming even if your C++ is rusty.  :slight_smile:

The CalculateUV () call there was something Corona was already doing, just pulled out into a function so I could reuse it.

Seems like kewl and high level discussion. I only know lua, but cant vertexes be added to that c++ with like a line of code? If the input is newPolygon( x, y, vertexes ) then cant those vertexes just be taken from that and be put to ”object.path.vertices” or something easy like that just like that? Cool topic anyway!!

@pixec, it should be fairly easy, but it’ll definitely take more than just a single line of code. I doubt anyone else will do it, so I might look into refreshing my C++ skills over the holidays and see if I could implement it.

@ pixec In its raw form this would mean basically keeping around two copies of the same information, which might add up with a lot of polygons. But maybe a property doing what XeduR’s code does would be handy.

@ XeduR On that note, best of luck! There is definitely a learning curve, and these objects in particular have paths and adapters and so on, but it’s fun.  :slight_smile:

@StarCrunch - nice work as always my friend!