I couldn’t find the bezier.lua file in corona code exchange.
It is not available in github either.
Someone share it here please or post it in github.
Thanks.
I couldn’t find the bezier.lua file in corona code exchange.
It is not available in github either.
Someone share it here please or post it in github.
Thanks.
I suspect you have a project that references this file. Where did you get the project? T&J use to have a spaceship project with bezier curves but that is just a guess. He doesn’t sell his templates anymore, but he is still around.
Otherwise, you have to give more detail for somebody to help you.
Adrian
Not sure if this is what you want:
------------------------------------------------- -- bezier.lua -- Version: 1.0 -- Author: Rajendra Pondel -- Email: neostar20@gmail.com -- Licence: MIT -- 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. local bezier = {} function bezier:curve(xv, yv) local reductor = {\_\_index = function(self, ind) return setmetatable({tree = self, level = ind}, {\_\_index = function(curves, ind) return function(t) local x1, y1 = curves.tree[curves.level-1][ind](t) local x2, y2 = curves.tree[curves.level-1][ind+1](t) return x1 + (x2 - x1) \* t, y1 + (y2 - y1) \* t end end}) end } local points = {} for i = 1, #xv do print(i, xv[i], yv[i]) points[i] = function(t) return xv[i], yv[i] end end return setmetatable({points}, reductor)[#points][1] end return bezier
Thanks, RoamingGamer! I was just looking for this module as well!
I’ve got a framework with a catmull-rom library, as well:
https://github.com/HoraceBury/CoronaFramework/blob/master/libs/catmull.lua
Excellent! Thanks Horacebury, that’s going in “the vault”!
There is also this one:
https://github.com/nshafer/Bezier
It’s not Corona specific but the Bezier.lua file is pretty simple to follow, and the main.lua file has some good sample code for reference.
I’ve got some stuff here too.
I’m actually employing this at the moment to test a use case for an open-source feature I’m working on: making nearly the full range of uniforms available to shaders that want it, as well as (in software, currently) instancing, mainly for the common situation of stepping through said uniforms.
The idea here is that you can make sort of a prototype, some object in its “natural” state, in this case a small axis-aligned rectangular grid. Then you string copies of it together along a curve, molding them to its shape in a vertex kernel. The uniforms are key to keeping large amounts of data (I only maintain a little geometry in the example, but other properties are possible as well), in particular when neighbor information is needed, without breaking batching.
This actually flips the curve equations around a bit, since you can precalculate a “geometry matrix” incorporating both the curve coefficents (how the points and / or tangents are combined) as well as sampled times along the prototype segment, e.g. t = 0, 1/4, 1/2, 3/4, 1. This way you only need a few multiplies by the point / tangent info rather than to churn through the curve formula each time.
These are quick examples of what I mean, in wireframe:
[media]https://www.youtube.com/watch?v=YMw229fFFg8[/media]
and solid:
[media]https://www.youtube.com/watch?v=T4-7dGC9HK0[/media]
The rather messy source behind it:
local cubic = require("spline\_ops.cubic") local verts = {} local N = 16 local Rows, Cols = 4, 8 --[[for i = 0, N do verts[#verts + 1] = i / N verts[#verts + 1] = 0 end for i = N, 0, -1 do verts[#verts + 1] = i / N verts[#verts + 1] = 1 end --]] for col = 1, Cols do for row = 1, Rows do local ulx, uly = (col - 1) / Cols, (row - 1) / Rows local urx, ury = col / Cols, uly local llx, lly = ulx, row / Rows local lrx, lry = urx, lly verts[#verts + 1] = ulx verts[#verts + 1] = uly verts[#verts + 1] = urx verts[#verts + 1] = ury verts[#verts + 1] = llx verts[#verts + 1] = lly verts[#verts + 1] = llx verts[#verts + 1] = lly verts[#verts + 1] = urx verts[#verts + 1] = ury verts[#verts + 1] = lrx verts[#verts + 1] = lry end end local back = display.newRect(display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight) back.isHitTestable, back.isVisible = true, false local MaxInstances = 10 local num\_points, poly = 0 local p, p1, p2 = {} local uni = {} --display.setDrawMode("wireframe") local function AddUniform4 (arr, index, a, b, c, d) uni[1], uni[2], uni[3], uni[4] = a, b, c, d arr:setUniforms(index, uni) end local K = N + 1 local Offset = 2 \* K back:addEventListener("touch", function(event) local phase = event.phase if phase == "began" then if num\_points \< MaxInstances + 1 then local arr, x, y = poly.fill.uniformArray, event.x, event.y if p1 then AddUniform4(arr, Offset + num\_points - 1, p2.x, p2.y, x - p1.x, y - p1.y) poly.isVisible=true poly.fill.numInstances = num\_points - 1 end if p2 then AddUniform4(arr, Offset + num\_points, x, y, x - p2.x, y - p2.y) end p1, p2 = p2, p1 or {} num\_points, p2.x, p2.y = num\_points + 1, x, y display.newCircle(x, y, 5):setFillColor(1, 0, 0) end display.getCurrentStage():setFocus(event.target) elseif phase == "ended" or phase == "cancelled" then display.getCurrentStage():setFocus(nil) end return true end) poly = display.newMesh{ vertices = verts }--newPolygon(display.contentCenterX, display.contentCenterY, verts) poly.isVisible = false graphics.defineEffect{ category = "generator", name = "uv", usesUniformVectors = true, vertexData = { { index = 0, name = "index", default = 0 } -- used if doing manual indexing }, vertex = ([[#define NUM\_SLOTS %i. P\_POSITION vec2 VertexKernel (P\_POSITION vec2 pos) { // ^^ Could also use pos to free up uvs; must account for centering // Precalculated coefficients (t^3, t^2, t, 1) and derivatives, mapped // by Hermite "geometry matrix" (just the constant coefficients of // the point and tangent equations), at t = xpos / N P\_POSITION vec4 cpos = CoronaUniformVector(xpos); P\_POSITION vec4 ctan = CoronaUniformVector(xpos + NUM\_SLOTS); // Nodes (point.xy, tangent.xy) follow these coeffs P\_UV float index = CoronaInstanceIndex + 2. \* NUM\_SLOTS; P\_POSITION vec4 pt1 = CoronaUniformVector(index); P\_POSITION vec4 pt2 = CoronaUniformVector(index + 1.); // 2x4 matrix P\_POSITION vec4 a = vec4(pt1.x, pt2.x, pt1.z, pt2.z); P\_POSITION vec4 b = vec4(pt1.y, pt2.y, pt1.w, pt2.w); // Transpose vector-matrix multiplies P\_POSITION vec2 p = vec2(dot(cpos, a), dot(cpos, b)); P\_POSITION vec2 t = vec2(dot(ctan, a), dot(ctan, b)); P\_POSITION vec2 f = normalize(t); P\_POSITION vec2 u = vec2(-f.y, +f.x); pos = p + u \* 2. \* (CoronaTexCoord.y - .5) \* 35.; return pos; }]]):format(K), fragment = [[P\_COLOR vec4 FragmentKernel (P\_UV vec2 uv) { return vec4(uv, 0., 1.); }]] } poly.fill.effect = "generator.custom.uv" local arr = poly.fill.uniformArray local pos, tan = {}, {} local function AddUniform (arr, index, o) AddUniform4(arr, index, o.a, o.b, o.c, o.d) end for i = 1, K do cubic.EvaluateCoeffs("hermite", pos, tan, (i - 1) / N) AddUniform(arr, i + 0, pos) AddUniform(arr, i + K, tan) end
The commented-out polygon stuff works passably, but the way a few vertices get laid out, you end up with one triangle outside the curve, which definitely does not look right. :) Thus the grid.
Anyhow, this is still rather a work in progress, with some other use cases in idea phase.
there are some really impressive offerings here!
but if you just want something simple…
-- factory local function CubicBezierEvaluator(x1,y1,x2,y2,x3,y3,x4,y4) return function(t) local a,b,c,d = (1-t)^3, 3\*(1-t)^2\*t, 3\*(1-t)\*t^2, t^3 return a\*x1+b\*x2+c\*x3+d\*x4, a\*y1+b\*y2+c\*y3+d\*y4 end end -- instance local f = CubicBezierEvaluator(100,300, 200,200, 150,400, 250,100) -- demo for t = 0,1,0.01 do local x,y = f(t) display.newCircle(x,y,2,2) end
I suspect you have a project that references this file. Where did you get the project? T&J use to have a spaceship project with bezier curves but that is just a guess. He doesn’t sell his templates anymore, but he is still around.
Otherwise, you have to give more detail for somebody to help you.
Adrian
Not sure if this is what you want:
------------------------------------------------- -- bezier.lua -- Version: 1.0 -- Author: Rajendra Pondel -- Email: neostar20@gmail.com -- Licence: MIT -- 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. local bezier = {} function bezier:curve(xv, yv) local reductor = {\_\_index = function(self, ind) return setmetatable({tree = self, level = ind}, {\_\_index = function(curves, ind) return function(t) local x1, y1 = curves.tree[curves.level-1][ind](t) local x2, y2 = curves.tree[curves.level-1][ind+1](t) return x1 + (x2 - x1) \* t, y1 + (y2 - y1) \* t end end}) end } local points = {} for i = 1, #xv do print(i, xv[i], yv[i]) points[i] = function(t) return xv[i], yv[i] end end return setmetatable({points}, reductor)[#points][1] end return bezier
Thanks, RoamingGamer! I was just looking for this module as well!
I’ve got a framework with a catmull-rom library, as well:
https://github.com/HoraceBury/CoronaFramework/blob/master/libs/catmull.lua
Excellent! Thanks Horacebury, that’s going in “the vault”!
There is also this one:
https://github.com/nshafer/Bezier
It’s not Corona specific but the Bezier.lua file is pretty simple to follow, and the main.lua file has some good sample code for reference.
I’ve got some stuff here too.
I’m actually employing this at the moment to test a use case for an open-source feature I’m working on: making nearly the full range of uniforms available to shaders that want it, as well as (in software, currently) instancing, mainly for the common situation of stepping through said uniforms.
The idea here is that you can make sort of a prototype, some object in its “natural” state, in this case a small axis-aligned rectangular grid. Then you string copies of it together along a curve, molding them to its shape in a vertex kernel. The uniforms are key to keeping large amounts of data (I only maintain a little geometry in the example, but other properties are possible as well), in particular when neighbor information is needed, without breaking batching.
This actually flips the curve equations around a bit, since you can precalculate a “geometry matrix” incorporating both the curve coefficents (how the points and / or tangents are combined) as well as sampled times along the prototype segment, e.g. t = 0, 1/4, 1/2, 3/4, 1. This way you only need a few multiplies by the point / tangent info rather than to churn through the curve formula each time.
These are quick examples of what I mean, in wireframe:
[media]https://www.youtube.com/watch?v=YMw229fFFg8[/media]
and solid:
[media]https://www.youtube.com/watch?v=T4-7dGC9HK0[/media]
The rather messy source behind it:
local cubic = require("spline\_ops.cubic") local verts = {} local N = 16 local Rows, Cols = 4, 8 --[[for i = 0, N do verts[#verts + 1] = i / N verts[#verts + 1] = 0 end for i = N, 0, -1 do verts[#verts + 1] = i / N verts[#verts + 1] = 1 end --]] for col = 1, Cols do for row = 1, Rows do local ulx, uly = (col - 1) / Cols, (row - 1) / Rows local urx, ury = col / Cols, uly local llx, lly = ulx, row / Rows local lrx, lry = urx, lly verts[#verts + 1] = ulx verts[#verts + 1] = uly verts[#verts + 1] = urx verts[#verts + 1] = ury verts[#verts + 1] = llx verts[#verts + 1] = lly verts[#verts + 1] = llx verts[#verts + 1] = lly verts[#verts + 1] = urx verts[#verts + 1] = ury verts[#verts + 1] = lrx verts[#verts + 1] = lry end end local back = display.newRect(display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight) back.isHitTestable, back.isVisible = true, false local MaxInstances = 10 local num\_points, poly = 0 local p, p1, p2 = {} local uni = {} --display.setDrawMode("wireframe") local function AddUniform4 (arr, index, a, b, c, d) uni[1], uni[2], uni[3], uni[4] = a, b, c, d arr:setUniforms(index, uni) end local K = N + 1 local Offset = 2 \* K back:addEventListener("touch", function(event) local phase = event.phase if phase == "began" then if num\_points \< MaxInstances + 1 then local arr, x, y = poly.fill.uniformArray, event.x, event.y if p1 then AddUniform4(arr, Offset + num\_points - 1, p2.x, p2.y, x - p1.x, y - p1.y) poly.isVisible=true poly.fill.numInstances = num\_points - 1 end if p2 then AddUniform4(arr, Offset + num\_points, x, y, x - p2.x, y - p2.y) end p1, p2 = p2, p1 or {} num\_points, p2.x, p2.y = num\_points + 1, x, y display.newCircle(x, y, 5):setFillColor(1, 0, 0) end display.getCurrentStage():setFocus(event.target) elseif phase == "ended" or phase == "cancelled" then display.getCurrentStage():setFocus(nil) end return true end) poly = display.newMesh{ vertices = verts }--newPolygon(display.contentCenterX, display.contentCenterY, verts) poly.isVisible = false graphics.defineEffect{ category = "generator", name = "uv", usesUniformVectors = true, vertexData = { { index = 0, name = "index", default = 0 } -- used if doing manual indexing }, vertex = ([[#define NUM\_SLOTS %i. P\_POSITION vec2 VertexKernel (P\_POSITION vec2 pos) { // ^^ Could also use pos to free up uvs; must account for centering // Precalculated coefficients (t^3, t^2, t, 1) and derivatives, mapped // by Hermite "geometry matrix" (just the constant coefficients of // the point and tangent equations), at t = xpos / N P\_POSITION vec4 cpos = CoronaUniformVector(xpos); P\_POSITION vec4 ctan = CoronaUniformVector(xpos + NUM\_SLOTS); // Nodes (point.xy, tangent.xy) follow these coeffs P\_UV float index = CoronaInstanceIndex + 2. \* NUM\_SLOTS; P\_POSITION vec4 pt1 = CoronaUniformVector(index); P\_POSITION vec4 pt2 = CoronaUniformVector(index + 1.); // 2x4 matrix P\_POSITION vec4 a = vec4(pt1.x, pt2.x, pt1.z, pt2.z); P\_POSITION vec4 b = vec4(pt1.y, pt2.y, pt1.w, pt2.w); // Transpose vector-matrix multiplies P\_POSITION vec2 p = vec2(dot(cpos, a), dot(cpos, b)); P\_POSITION vec2 t = vec2(dot(ctan, a), dot(ctan, b)); P\_POSITION vec2 f = normalize(t); P\_POSITION vec2 u = vec2(-f.y, +f.x); pos = p + u \* 2. \* (CoronaTexCoord.y - .5) \* 35.; return pos; }]]):format(K), fragment = [[P\_COLOR vec4 FragmentKernel (P\_UV vec2 uv) { return vec4(uv, 0., 1.); }]] } poly.fill.effect = "generator.custom.uv" local arr = poly.fill.uniformArray local pos, tan = {}, {} local function AddUniform (arr, index, o) AddUniform4(arr, index, o.a, o.b, o.c, o.d) end for i = 1, K do cubic.EvaluateCoeffs("hermite", pos, tan, (i - 1) / N) AddUniform(arr, i + 0, pos) AddUniform(arr, i + K, tan) end
The commented-out polygon stuff works passably, but the way a few vertices get laid out, you end up with one triangle outside the curve, which definitely does not look right. :) Thus the grid.
Anyhow, this is still rather a work in progress, with some other use cases in idea phase.
there are some really impressive offerings here!
but if you just want something simple…
-- factory local function CubicBezierEvaluator(x1,y1,x2,y2,x3,y3,x4,y4) return function(t) local a,b,c,d = (1-t)^3, 3\*(1-t)^2\*t, 3\*(1-t)\*t^2, t^3 return a\*x1+b\*x2+c\*x3+d\*x4, a\*y1+b\*y2+c\*y3+d\*y4 end end -- instance local f = CubicBezierEvaluator(100,300, 200,200, 150,400, 250,100) -- demo for t = 0,1,0.01 do local x,y = f(t) display.newCircle(x,y,2,2) end