Created
May 20, 2013 10:41
-
-
Save loopspace/5611554 to your computer and use it in GitHub Desktop.
Library Utilities Release v2 -A library of utility classes and functions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Library Utilities Tab Order Version: 2 | |
| ------------------------------ | |
| This file should not be included in the Codea project. | |
| #ChangeLog | |
| #Main | |
| #Lengths | |
| #Boolean | |
| #MathsUtilities | |
| #MeshUtilities | |
| #RoundedRectangle | |
| #TouchUtilities | |
| #Playlist |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --[==[ | |
| -- Saving or reading a boolean value. | |
| local Boolean = {} | |
| function Boolean.readData(t,k,b) | |
| local f | |
| if t == "global" then | |
| f = readGlobalData | |
| elseif t == "project" then | |
| f = readProjectData | |
| else | |
| f = readLocalData | |
| end | |
| local bol = f(k) | |
| if bol then | |
| if bol == 0 then | |
| return false | |
| else | |
| return true | |
| end | |
| else | |
| if b then | |
| return true | |
| else | |
| return false | |
| end | |
| end | |
| end | |
| function Boolean.saveData(t,k,b) | |
| local f | |
| if t == "global" then | |
| f = saveGlobalData | |
| elseif t == "project" then | |
| f = saveProjectData | |
| else | |
| f = saveLocalData | |
| end | |
| if b then | |
| f(k,1) | |
| else | |
| f(k,0) | |
| end | |
| end | |
| return Boolean | |
| --]==] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --[[ | |
| ChangeLog | |
| ========= | |
| v2.0 Split into separate projects: "Library Utilities" is for | |
| useful things of a general nature. | |
| v1.0 Converted to use toadkick's cmodule for importing | |
| and Briarfox's AutoGist for versionning. | |
| It needs toadkick's code from | |
| https://gist.github.com/apendley/5411561 | |
| tested with version 0.0.8 | |
| To use without AutoGist, comment out the lines in setup. | |
| --]] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --[==[ | |
| function getLength(l) | |
| local n = tonumber(l) | |
| if n then | |
| return n | |
| end | |
| local i,j,m,u = string.find(l,"^(%d*)(%D*)$") | |
| if i then | |
| if u == "px" or u == "pcx" then | |
| return m | |
| elseif u == "pt" then | |
| return m * 3.653 | |
| elseif u == "in" then | |
| return m * 264 | |
| elseif u == "cm" then | |
| return m * 670.56 | |
| elseif u == "mm" then | |
| return m * 6705.6 | |
| elseif u == "m" then | |
| return m * 67.056 | |
| elseif u == "em" then | |
| local t = fontMetrics() | |
| return m * t.size | |
| elseif u == "en" then | |
| local t = fontMetrics() | |
| return m * t.size/2 | |
| elseif u == "ex" then | |
| local t = fontMetrics() | |
| return m * t.xHeight | |
| elseif u == "lh" then | |
| local _,h = textSize("x") | |
| return m * h | |
| else | |
| return nil | |
| end | |
| end | |
| return nil | |
| end | |
| function evalLength(s) | |
| if type(s) == "function" then | |
| s = s() | |
| end | |
| s = string.gsub(s,"(%d+%a+)", | |
| function(n) return getLength(n) or n end) | |
| s = "local s = " .. s .. " return s" | |
| local f = loadstring(s) | |
| s = f() | |
| return s | |
| end | |
| cmodule.gexport { | |
| evalLength = evalLength | |
| } | |
| --]==] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| VERSION = 2.0 | |
| clearProjectData() | |
| -- DEBUG = true | |
| -- Use this function to perform your initial setup | |
| function setup() | |
| if AutoGist then | |
| autogist = AutoGist("Library Utilities","A library of utility classes and functions.",VERSION) | |
| autogist:backup(true) | |
| end | |
| --displayMode(FULLSCREEN_NO_BUTTONS) | |
| cmodule "Library CModule" | |
| cimport "TestSuite" | |
| local Touches = cimport "Touch" | |
| local UI = cimport "UI" | |
| local Debug = cimport "Debug" | |
| local Playlist = cimport "Playlist" | |
| local Colour = unpack(cimport "Colour",nil) | |
| cimport "ColourNames" | |
| cimport "PictureBrowser" | |
| cimport "Menu" | |
| cimport "Keypad" | |
| cimport "Keyboard" | |
| local TextNode = cimport "TextNode" | |
| if cmodule.loaded("Menu") then | |
| print("Menu loaded") | |
| else | |
| print("Menu not loaded") | |
| end | |
| local View = cimport "View" | |
| local Quaternion = cimport "Quaternion" | |
| local Explosion = cimport "Explosion" | |
| --print(Quaternion(1,.56789,0,0)) | |
| touches = Touches() | |
| ui = UI(touches) | |
| debug = Debug({ui = ui}) | |
| ui:systemmenu() | |
| ui:helpmenu() | |
| ui:addMessage("This is a system message, hello everyone.") | |
| playlist = Playlist({ ui = ui}) | |
| testsuite.initialise({ui = ui}) | |
| --[[ | |
| colfn = function(col) | |
| print(col) | |
| ui:getColour(col,colfn) | |
| return true | |
| end | |
| colfn(Colour.svg.Black) | |
| --]] | |
| debug:log({ | |
| name = "Screen north west", | |
| message = function() local x,y = RectAnchorOf(Screen,"north west") return x .. ", " .. y end | |
| }) | |
| --debug:activate() | |
| ui:setPictureList({directory = "Documents", camera = true, filter = function(n,w,h) return math.min(w,h) > 500 end}) | |
| --ui:getPicture(function(i) img = i return true end) | |
| --print(USRotateCCW(vec2(1,0))) | |
| ui:declareKeyboard({name = "ArialMT", type = "fullqwerty"}) | |
| ui:useKeyboard("fullqwerty", | |
| function(k) print(k) return false end) | |
| print("Textnode") | |
| tn = TextNode({ | |
| pos = function() return WIDTH/2,800 end, | |
| anchor = "centre", | |
| --angle = 30, | |
| ui = ui, | |
| fit = true, | |
| maxHeight = HEIGHT, | |
| }) | |
| watch("tn.numlines") | |
| watch("dbug") | |
| touches:pushHandler(tn) | |
| -- | |
| print(PORTRAIT) | |
| print(PORTRAIT_UPSIDE_DOWN) | |
| print(PORTRAIT_ANY) | |
| print(LANDSCAPE_LEFT) | |
| print(LANDSCAPE_RIGHT) | |
| print(LANDSCAPE_ANY) | |
| print(ANY) | |
| --ui:setOrientation(PORTRAIT_UPSIDE_DOWN) | |
| -- ui:supportedOrientations(PORTRAIT_UPSIDE_DOWN) | |
| view = View(ui,touches) | |
| parameter.watch("view.baseRotation") | |
| parameter.watch("stuff[1]") | |
| parameter.watch("stack") | |
| shape = mesh() | |
| shape.texture = "Documents:Daniel at barnehage" | |
| local x,y,z = 1,1,1 | |
| shape.vertices = { | |
| vec3(x,0,0), | |
| vec3(0,y,0), | |
| vec3(0,0,z), | |
| vec3(0,0,0), | |
| vec3(0,y,0), | |
| vec3(0,0,z), | |
| vec3(x,0,0), | |
| vec3(0,0,0), | |
| vec3(0,0,z), | |
| vec3(x,0,0), | |
| vec3(0,y,0), | |
| vec3(0,0,0) | |
| } | |
| shape.colors = { | |
| Colour.svg.Red, | |
| Colour.svg.Green, | |
| Colour.svg.Blue, | |
| Colour.svg.White, | |
| Colour.svg.Green, | |
| Colour.svg.Blue, | |
| Colour.svg.Red, | |
| Colour.svg.White, | |
| Colour.svg.Blue, | |
| Colour.svg.Red, | |
| Colour.svg.Green, | |
| Colour.svg.White | |
| } | |
| view.eye = vec3(5,0,0) | |
| view.range = .25 | |
| perspective(40,WIDTH/HEIGHT) | |
| print(projectionMatrix()) | |
| camera(0,0,15,0,0,0,0,1,0) | |
| print(viewMatrix()) | |
| camera(0,0,-15,0,0,0,0,1,0) | |
| print(viewMatrix()) | |
| --watch("dbg") | |
| --ui:getCurve(vec4(0,0,3,-2),function(v) print(v) return true end) | |
| --ui:getColour(function(c) print(c) return true end) | |
| tw = {t = 0,s=0} | |
| ui:setTimer(5,function() tween(5,tw,{t = 1,s = 0}) return true end) | |
| ui:setTimer(12,function() tween(5,tw,{t = 1,s = 1}) return true end) | |
| ui:setTimer(18,function() tw = {t = 0,s = 1} return true end) | |
| ui:setTimer(19,function() tween(5,tw,{t = 1,s = 0}) return true end) | |
| print(Quaternion.Rotation(1,3,4,5)) | |
| parameter.watch("vm") | |
| parameter.watch("qt") | |
| qslp = Quaternion.unit():make_slerp(Quaternion(1,0,0,0)) | |
| qlp = Quaternion.unit():make_lerp(Quaternion(-1,0,0,0)) | |
| explosion = Explosion({ | |
| image = "Cargo Bot:Codea Icon", | |
| trails = true, | |
| centre = vec2(WIDTH/2,HEIGHT/2) | |
| }) | |
| --explosion:activate(1,5) | |
| --ui:addNotice({text = "Watch carefully"}) | |
| ui:getNumber(function(n) print(n) end) | |
| end | |
| -- This function gets called once every frame | |
| function draw() | |
| -- process touches and taps | |
| touches:draw() | |
| background(34, 47, 53, 255) | |
| --testsuite.draw() | |
| --playlist:draw() | |
| --[[ | |
| fill(255, 255, 255, 255) | |
| pushMatrix() | |
| translate(WIDTH/2,HEIGHT/2) | |
| rotate(45) | |
| text("hello",0,0) | |
| popMatrix() | |
| --]] | |
| if img then | |
| local w,h = img.width,img.height | |
| local asp = math.min(WIDTH/w,HEIGHT/h,1) | |
| --sprite(img,WIDTH/2,HEIGHT/2,w*asp,h*asp) | |
| end | |
| tn:draw() | |
| pushMatrix() | |
| view:draw() | |
| vm = viewMatrix() | |
| qt = qslp(tw.t) | |
| qt = qt*qlp(tw.s) | |
| --modelMatrix(qt:tomatrix()) | |
| --perspective(40,WIDTH/HEIGHT) | |
| --camera(10,10,10,0,0,0,0,1,0) | |
| shape:draw() | |
| popMatrix() | |
| resetMatrix() | |
| viewMatrix(matrix()) | |
| ortho() | |
| explosion:draw() | |
| ui:draw() | |
| debug:draw() | |
| touches:show() | |
| end | |
| function touched(touch) | |
| touches:addTouch(touch) | |
| end | |
| function orientationChanged(o) | |
| if ui then | |
| ui:orientationChanged(o) | |
| end | |
| end | |
| function fullscreen() | |
| end | |
| function reset() | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --[==[ | |
| --[[ | |
| Some mathematical utilities. | |
| --]] | |
| function Ordinal(n) | |
| local k = n%10 | |
| local th = "th" | |
| if k == 1 then | |
| th = "st" | |
| elseif k == 2 then | |
| th = "nd" | |
| elseif k == 3 then | |
| th = "rd" | |
| end | |
| return n .. th | |
| end | |
| function Regression(t) | |
| local n, xy, x, y, xx, yy = 0,0,0,0,0,0 | |
| for k,v in ipairs(t) do | |
| n = n + 1 | |
| xy = xy + v.x*v.y | |
| x = x + v.x | |
| y = y + v.y | |
| xx = xx + v.x*v.x | |
| yy = yy + v.y*v.y | |
| end | |
| local d = n*xx - x*x | |
| if d == 0 then | |
| return false,false,Matrix({{0,0},{0,0}}) | |
| end | |
| local matrix | |
| if Matrix then | |
| matrix = Matrix({{xx,x},{x,n}}) | |
| end | |
| return (n*xy - x*y)/d, | |
| (-x*xy + xx*y)/d, | |
| matrix, | |
| (n*xy -x*y)^2/((n*xx-x*x)*(n*yy-y*y)) | |
| end | |
| function ApplyAffine(m,v) | |
| if v then | |
| return v.x*m[1] + v.y*m[2] + m[3] | |
| else | |
| applyMatrix(matrix( | |
| m[1].x, m[1].y, 0, 0, | |
| m[2].x, m[2].y, 0, 0, | |
| 0,0,1,0, | |
| m[3].x, m[3].y, 0, 1 | |
| )) | |
| end | |
| end | |
| function USRotateCW(v) | |
| return ApplyAffine({vec2(0,-1),vec2(1,0),vec2(0,1)},v) | |
| end | |
| function USRotateCCW(v) | |
| return ApplyAffine({vec2(0,1),vec2(-1,0),vec2(1,0)},v) | |
| end | |
| function USReflectV(v) | |
| return ApplyAffine({vec2(-1,0),vec2(0,1),vec2(1,0)},v) | |
| end | |
| function USReflectH(v) | |
| return ApplyAffine({vec2(1,0),vec2(0,-1),vec2(0,1)},v) | |
| end | |
| local USCoordinates = {} | |
| USCoordinates[PORTRAIT] = {vec2(1,0),vec2(0,1),vec2(0,0)} | |
| USCoordinates[PORTRAIT_UPSIDE_DOWN] = {vec2(-1,0),vec2(0,-1),vec2(1,1)} | |
| USCoordinates[LANDSCAPE_LEFT] = {vec2(0,-1),vec2(1,0),vec2(0,1)} | |
| USCoordinates[LANDSCAPE_RIGHT] = {vec2(0,1),vec2(-1,0),vec2(1,0)} | |
| function USOrientation(o,v) | |
| return ApplyAffine(USCoordinates[o],v) | |
| end | |
| local InvUSCoordinates = {} | |
| InvUSCoordinates[PORTRAIT] = {vec2(1,0),vec2(0,1),vec2(0,0)} | |
| InvUSCoordinates[PORTRAIT_UPSIDE_DOWN] = {vec2(-1,0),vec2(0,-1),vec2(1,1)} | |
| InvUSCoordinates[LANDSCAPE_LEFT] = {vec2(0,1),vec2(-1,0),vec2(1,0)} | |
| InvUSCoordinates[LANDSCAPE_RIGHT] = {vec2(0,-1),vec2(1,0),vec2(0,1)} | |
| function InvUSOrientation(o,v) | |
| return ApplyAffine(InvUSCoordinates[o],v) | |
| end | |
| function TriangleArea(a,b,c) | |
| return math.abs( | |
| a:dot(b:rotate90()) | |
| + b:dot(c:rotate90()) | |
| + c:dot(a:rotate90()) | |
| )/2 | |
| end | |
| function applymatrix4(v,m) | |
| local u = {} | |
| u[1] = m[1]*v[1] + m[5]*v[2] + m[09]*v[3] + m[13]*v[4] | |
| u[2] = m[2]*v[1] + m[6]*v[2] + m[10]*v[3] + m[14]*v[4] | |
| u[3] = m[3]*v[1] + m[7]*v[2] + m[11]*v[3] + m[15]*v[4] | |
| u[4] = m[4]*v[1] + m[8]*v[2] + m[12]*v[3] + m[16]*v[4] | |
| return u | |
| end | |
| function cofactor4(m) | |
| local rm = matrix() | |
| local sgn,l | |
| local fm = {} | |
| for k=1,16 do | |
| fm = {} | |
| l = math.floor((k-1)/4) + 1 + 4*((k-1)%4) | |
| sgn = (-1)^(math.floor((k-1)/4))*(-1)^((k-1)%4) | |
| for j=1,16 do | |
| if j%4 ~= k%4 | |
| and math.floor((j-1)/4) ~= math.floor((k-1)/4) | |
| then | |
| table.insert(fm,m[j]) | |
| end | |
| end | |
| rm[l] = sgn*Det3(fm) | |
| end | |
| return rm | |
| end | |
| function Det3(t) | |
| return t[1]*t[5]*t[9] | |
| + t[2]*t[6]*t[7] | |
| + t[3]*t[4]*t[8] | |
| - t[3]*t[5]*t[7] | |
| - t[2]*t[4]*t[9] | |
| - t[1]*t[6]*t[8] | |
| end | |
| function applymatrix3(v,m) | |
| local u = {} | |
| u[1] = m[1]*v[1] + m[4]*v[2] + m[7]*v[3] | |
| u[2] = m[2]*v[1] + m[5]*v[2] + m[8]*v[3] | |
| u[3] = m[3]*v[1] + m[6]*v[2] + m[9]*v[3] | |
| return u | |
| end | |
| function cofactor3(m) | |
| local rm = {} | |
| local sgn,l | |
| local fm = {} | |
| for k=1,9 do | |
| fm = {} | |
| l = math.floor((k-1)/3) + 1 + 3*((k-1)%3) | |
| sgn = (-1)^(math.floor((k-1)/3))*(-1)^((k-1)%3) | |
| for j=1,9 do | |
| if j%3 ~= k%3 | |
| and math.floor((j-1)/3) ~= math.floor((k-1)/3) | |
| then | |
| table.insert(fm,m[j]) | |
| end | |
| end | |
| rm[l] = sgn*Det2(fm) | |
| end | |
| return rm | |
| end | |
| function Det2(t) | |
| return t[1]*t[4] - t[2]*t[3] | |
| end | |
| function RandomVec3() | |
| local th = 2*math.pi*math.random() | |
| local z = 2*math.random() - 1 | |
| local r = math.sqrt(1 - z*z) | |
| return vec3(r*math.cos(th),r*math.sin(th),z) | |
| end | |
| function RandomBasisR3() | |
| local th = 2*math.pi*math.random() | |
| local cth = math.cos(th) | |
| local sth = math.sin(th) | |
| local a = vec3(cth,sth,0) | |
| local b = vec3(-sth,cth,0) | |
| local c = vec3(0,0,1) | |
| local v = RandomVec3() | |
| a = a - 2*v:dot(a)*v | |
| b = b - 2*v:dot(b)*v | |
| c = c - 2*v:dot(c)*v | |
| return {a,b,c} | |
| end | |
| function SO3(u,v) | |
| if u == vec3(0,0,0) then | |
| if v == vec3(0,0,0) then | |
| return {vec3(1,0,0),vec3(0,1,0),vec3(0,0,1)} | |
| end | |
| u,v = v,u | |
| end | |
| if u:cross(v) == vec3(0,0,0) then | |
| if u.x == 0 and u.y == 0 then | |
| v = vec3(1,0,0) | |
| else | |
| v = vec3(u.y,-u.x,0) | |
| end | |
| end | |
| local t = GramSchmidt({u,v}) | |
| t[3] = t[1]:cross(t[2]) | |
| return t | |
| end | |
| function GramSchmidt(t) | |
| local o = {} | |
| local w | |
| for k,v in ipairs(t) do | |
| w = v | |
| for l,u in ipairs(o) do | |
| w = w - w:dot(u)*u | |
| end | |
| if w ~= vec3(0,0,0) then | |
| w = w:normalize() | |
| table.insert(o,w) | |
| end | |
| end | |
| return o | |
| end | |
| cmodule.gexport { | |
| Ordinal = Ordinal, | |
| Regression = Regression, | |
| ApplyAffine = ApplyAffine, | |
| USRotateCW = USRotateCW, | |
| USRotateCCW = USRotateCCW, | |
| USReflectV = USReflectV, | |
| USReflectH = USReflectH, | |
| USOrientation = USOrientation, | |
| InvUSOrientation = InvUSOrientation, | |
| TriangleArea = TriangleArea, | |
| applymatrix4 = applymatrix4, | |
| cofactor4 = cofactor4, | |
| Det3 = Det3, | |
| applymatrix3 = applymatrix3, | |
| cofactor3 = cofactor3, | |
| Det2 = Det2, | |
| RandomVec3 = RandomVec3, | |
| RandomBasisR3 = RandomBasisR3, | |
| SO3 = SO3, | |
| GramSchmidt = GramSchmidt | |
| } | |
| --]==] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --[==[ | |
| -- Mesh Utilities | |
| --[[ | |
| Utility functions for meshes. These all add shapes to a mesh, sort of. | |
| The older routines modified tables for vertices and colours whereas the newer ones modified the mesh directly. They should be standardised. | |
| --]] | |
| --[[ | |
| Vertex ordering: | |
| 1 -- 2 | |
| | | | |
| 3 -- 4 | |
| --]] | |
| function addQuad(t) | |
| local m = t.mesh | |
| local n = t.position or 0 | |
| if n > m.size - 12 then | |
| m:resize(n + 300) | |
| end | |
| local v = t.vertices | |
| for k,l in ipairs({1,2,3,2,3,4}) do | |
| m:vertex(n+k,v[l][1]) | |
| if v[l][2] then | |
| m:color(n+k,v[l][2]) | |
| end | |
| if v[l][3] then | |
| m:texCoord(n+k,v[l][3]) | |
| end | |
| end | |
| return n + 6 | |
| end | |
| function addTriangle(t) | |
| local m = t.mesh | |
| local n = t.position or 0 | |
| if n > m.size - 12 then | |
| m:resize(n + 300) | |
| end | |
| local v = t.vertices | |
| for k,l in ipairs({1,2,3}) do | |
| m:vertex(n+k,v[l][1]) | |
| m:color(n+k,v[l][2]) | |
| end | |
| return n + 3 | |
| end | |
| --[[ | |
| Adds a rounded rectangle to an existing mesh | |
| --]] | |
| function addRoundedRect(t) | |
| local m = t.mesh | |
| local x = t.x | |
| local y = t.y | |
| local w = t.width or 0 | |
| local h = t.height or 0 | |
| local s = t.radius or 10 | |
| local c = t.corners or 0 | |
| local a = t.anchor | |
| local fc = t.colour or fill() | |
| if a then | |
| x,y = RectAnchorAt(x,y,w,h,a) | |
| end | |
| local v = {} | |
| local nv = 0 | |
| local ce = vec2(x + w/2,y + h/2) | |
| local n = 4 | |
| local o,dx,dy | |
| for j = 1,4 do | |
| dx = -1 + 2*(j%2) | |
| dy = -1 + 2*(math.floor(j/2)%2) | |
| o = ce + vec2(dx * (w/2 - s), dy * (h/2 - s)) | |
| if math.floor(c/2^(j-1))%2 == 0 then | |
| for i = 1,n do | |
| table.insert(v,o) | |
| table.insert(v,o + vec2(dx * s * math.cos((i-1) * math.pi/(2*n)), dy * s * math.sin((i-1) * math.pi/(2*n)))) | |
| table.insert(v,o + vec2(dx * s * math.cos(i * math.pi/(2*n)), dy * s * math.sin(i * math.pi/(2*n)))) | |
| end | |
| nv = nv + 3*n | |
| else | |
| table.insert(v,o) | |
| table.insert(v,o + vec2(dx * s,0)) | |
| table.insert(v,o + vec2(dx * s,dy * s)) | |
| table.insert(v,o) | |
| table.insert(v,o + vec2(0,dy * s)) | |
| table.insert(v,o + vec2(dx * s,dy * s)) | |
| nv = nv + 6 | |
| end | |
| end | |
| local nrv = m.size | |
| m:resize(nrv + nv) | |
| for k,ve in ipairs(v) do | |
| m:vertex(nrv + k, ve) | |
| m:color(nrv+k,fc) | |
| end | |
| local ri = m:addRect(ce.x,ce.y,w,h-2*s) | |
| m:setRectColor(ri,fc) | |
| ri = m:addRect(ce.x,ce.y + (h-s)/2,w-2*s,s) | |
| m:setRectColor(ri,fc) | |
| ri = m:addRect(ce.x,ce.y - (h-s)/2,w-2*s,s) | |
| m:setRectColor(ri,fc) | |
| end | |
| function AddPlank(t) | |
| local w = t.width | |
| local h = t.height | |
| local d = t.depth | |
| local o = t.origin | |
| local cube = {} | |
| local j,k,l | |
| for i=0,7 do | |
| j = 2*(i%2)-1 | |
| k = 2*(math.floor(i/2)%2)-1 | |
| l = 2*(math.floor(i/4)%2)-1 | |
| table.insert(cube, o + j*w + k*h + l* d) | |
| end | |
| return AddCube({ | |
| vertices = t.vertices, | |
| colours = t.colours, | |
| light = t.light, | |
| cube = cube, | |
| colour = t.colour or Colour.x11.Burlywood3 | |
| }) | |
| end | |
| function AddSlab(t) | |
| local sc = t.startCentre | |
| local sh = t.startHeight | |
| local sw = t.startWidth | |
| local ec = t.endCentre | |
| local eh = t.endHeight | |
| local ew = t.endWidth | |
| local cube = {} | |
| local j,k | |
| for i=0,3 do | |
| j = 2*(i%2)-1 | |
| k = 2*(math.floor(i/2)%2)-1 | |
| table.insert(cube,sc + j*sh + k*sw) | |
| table.insert(cube,ec + j*eh + k*ew) | |
| end | |
| return AddCube({ | |
| vertices = t.vertices, | |
| colours = t.colours, | |
| light = t.light, | |
| cube = cube, | |
| colour = t.colour or Colour.x11.Burlywood3 | |
| }) | |
| end | |
| function AddHalfTube(t) | |
| local r = t.radius | |
| local b = { | |
| {t.startCentre,t.startWidth,t.startHeight}, | |
| {t.endCentre,t.endWidth,t.endHeight} | |
| } | |
| local vertices = t.vertices | |
| local colours = t.colours | |
| local c = t.colour or Colour.svg.DarkSlateBlue | |
| local l = t.light:normalize() | |
| local n = t.number or 36 | |
| local step = math.pi/n | |
| local ang,pang,lc,ver | |
| for i = 1,n do | |
| ang = i*step | |
| pang = (i-1)*step | |
| for k,v in ipairs({ | |
| {1,pang}, | |
| {1,ang}, | |
| {2,ang}, | |
| {2,ang}, | |
| {1,pang}, | |
| {2,pang} | |
| }) do | |
| ver = math.cos(v[2]) * b[v[1]][2] + math.sin(v[2]) * b[v[1]][3] | |
| table.insert(vertices,b[v[1]][1] + ver) | |
| lc = l:dot(ver) | |
| table.insert(colours,Colour.shade(c,50 + 25*lc)) | |
| end | |
| end | |
| return vertices, colours | |
| end | |
| function AddTube(t) | |
| local r = t.radius | |
| local b = { | |
| {t.startCentre,t.startWidth,t.startHeight,t.startTexture}, | |
| {t.endCentre,t.endWidth,t.endHeight,t.endTexture} | |
| } | |
| local vertices = t.vertices | |
| local colours = t.colours | |
| local texcoords = t.texCoords | |
| local normals = t.normals | |
| local c = t.colour or Colour.svg.DarkSlateBlue | |
| local l = t.light | |
| if l then | |
| l = l:normalize() | |
| end | |
| local n = t.number or 36 | |
| local step = 2*math.pi/n | |
| local ang,pang,lc,ver | |
| for i = 1,n do | |
| ang = i*step | |
| pang = (i-1)*step | |
| for k,v in ipairs({ | |
| {1,pang}, | |
| {1,ang}, | |
| {2,ang}, | |
| {2,ang}, | |
| {1,pang}, | |
| {2,pang} | |
| }) do | |
| ver = math.cos(v[2]) * b[v[1]][2] + math.sin(v[2]) * b[v[1]][3] | |
| table.insert(vertices,b[v[1]][1] + ver) | |
| if l then | |
| lc = l:dot(ver) | |
| table.insert(colours,Colour.shade(c,50 + 25*lc)) | |
| else | |
| table.insert(colours,c) | |
| end | |
| if texcoords then | |
| table.insert(texcoords, | |
| vec2(b[v[1]][4],v[2]/(2*math.pi))) | |
| end | |
| if normals then | |
| table.insert(normals, | |
| ver:normalize()) | |
| end | |
| end | |
| end | |
| return vertices, colours, texcoords, normals | |
| end | |
| -- cube faces are in binary order: 000, 001, 010, 011 etc | |
| local CubeFaces = { | |
| {1,2,3,4}, | |
| {5,7,6,8}, | |
| {1,5,2,6}, | |
| {3,4,7,8}, | |
| {2,6,4,8}, | |
| {1,3,5,7} | |
| } | |
| function AddCube(t) | |
| local cube = t.cube | |
| local vertices = t.vertices or {} | |
| local colours = t.colours or {} | |
| local normals = t.normals or {} | |
| local c = t.colour or Colour.x11.Burlywood3 | |
| local l = t.light:normalize() | |
| local faces = t.faces or CubeFaces | |
| local lc,n | |
| for k,v in ipairs(faces) do | |
| n = (cube[v[3]] - cube[v[1]]):cross(cube[v[2]] - cube[v[1]]) | |
| if n ~= vec3(0,0,0) then | |
| n = n:normalize() | |
| lc = n:dot(l) | |
| end | |
| for i,u in ipairs({1,2,3,2,3,4}) do | |
| table.insert(vertices,cube[v[u]]) | |
| table.insert(normals,n) | |
| table.insert(colours, | |
| Colour.shade(c,75 + 25*lc) | |
| ) | |
| end | |
| end | |
| return vertices,colours,normals | |
| end | |
| function AddJewel(t) | |
| local o = t.origin | |
| local a = SO3(t.axis,vec3(0,0,1)) | |
| local n = t.sides | |
| local la = t.axis:len() | |
| for i = 1,3 do | |
| a[i] = la*a[i] | |
| end | |
| local vertices = t.vertices or {} | |
| local colours = t.colours or {} | |
| local clr = t.colour or Colour.svg.IndianRed | |
| local l = t.light:normalize() | |
| local th = math.pi/n | |
| local cs = math.cos(th) | |
| local sn = math.sin(th) | |
| local h = (1 - cs)/(1 + cs) | |
| local nh = 1/(1+h) | |
| local nhl = 1/math.sqrt(1 + nh^2) | |
| local k,b,c,d,nml,cl,nv | |
| b = a[2] | |
| c = cs*a[2] + sn*a[3] | |
| d = -sn*a[2] + cs*a[3] | |
| nv = 0 | |
| for i = 1,2*n do | |
| k = 2*(i%2) - 1 | |
| for j = -1,1,2 do | |
| table.insert(vertices,o + j*a[1]) | |
| table.insert(vertices,o + h*k*a[1] + b) | |
| table.insert(vertices,o - h*k*a[1] + c) | |
| nml = j*nh*a[1] + .5*(1 - j*k)*b + .5*(1 + j*k)*c | |
| cl = nml:dot(l)/nhl | |
| for m=1,3 do | |
| table.insert(colours,Colour.shade(clr,75 + 25*cl)) | |
| end | |
| nv = nv + 3 | |
| end | |
| b = c | |
| c = cs*c + sn*d | |
| d = -sn*b + cs*d | |
| end | |
| return vertices,colours,nv | |
| end | |
| function AddStar(t) | |
| local o = t.origin | |
| local s = t.size | |
| local l = t.light:normalize()/(math.sqrt(3)) | |
| local vertices = t.vertices or {} | |
| local colours = t.colours or {} | |
| local b = RandomBasisR3() | |
| local v,n,c | |
| local bb = {} | |
| for i=0,7 do | |
| bb[1] = 2*(i%2)-1 | |
| bb[2] = 2*(math.floor(i/2)%2)-1 | |
| bb[3] = 2*(math.floor(i/4)%2)-1 | |
| v = bb[1]*b[1] + bb[2]*b[2] + bb[3]*b[3] | |
| n = math.abs(v:dot(l)) | |
| c = Colour.shade(Colour.x11["LemonChiffon" .. math.random(1,4)], 70+n*30) | |
| for m=1,3 do | |
| table.insert(colours,c) | |
| table.insert(vertices,o+s*(v - 2*bb[m]*b[m])) | |
| end | |
| end | |
| return vertices,colours | |
| end | |
| cmodule.gexport { | |
| addQuad = addQuad, | |
| addTriangle = addTriangle, | |
| addRoundedRect = addRoundedRect, | |
| AddPlank = AddPlank, | |
| AddSlab = AddSlab, | |
| AddTube = AddTube, | |
| AddHalfTube = AddHalfTube, | |
| AddCube = AddCube, | |
| AddJewel = AddJewel, | |
| AddStar = AddStar | |
| } | |
| --]==] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --[==[ | |
| -- Playlist | |
| local Playlist = class() | |
| cimport "Menu" | |
| function Playlist:init(t) | |
| t = t or {} | |
| self.startat = t.startTime or 0 | |
| if t.skipTo then | |
| self.skip = t.skipTo | |
| self.startat = self.startat - t.skipTo | |
| end | |
| self.current = t.startTime or 0 | |
| self.lastaction = t.lastAction | |
| self.pauseaction = t.pauseAction | |
| self.resumeaction = t.resumeAction | |
| self.events = {} | |
| local attach = true | |
| if t.standalone then | |
| attach = false | |
| end | |
| local mopts = t.menuOpts or {} | |
| local title = t.title or "Playlist" | |
| local m = t.ui:addMenu({title = title, attach = attach, menuOpts = mopts}) | |
| m:addItem({title = "Start", | |
| action = function() | |
| self:start() | |
| return true | |
| end, | |
| highlight = function() | |
| return self.running | |
| end | |
| }) | |
| m:addItem({title = "Stop", | |
| action = function() | |
| self:stop() | |
| return true | |
| end | |
| }) | |
| m:addItem({title = "Pause", | |
| action = function() | |
| self:pause() | |
| return true | |
| end, | |
| highlight = function() | |
| return self.paused | |
| end | |
| }) | |
| m:addItem({title = "Resume", | |
| action = function() | |
| self:resume() | |
| return true | |
| end | |
| }) | |
| end | |
| function Playlist:addEvent(t) | |
| t = t or {} | |
| local ti = t.time or 0 | |
| if t.relative then | |
| ti = ti + self.current | |
| end | |
| if t.duration then | |
| self.current = ti + t.duration | |
| table.insert(self.events,{ti,t.event}) | |
| elseif t.step and t.number then | |
| for k = 1,t.number do | |
| table.insert(self.events,{ti,t.event}) | |
| ti = ti + t.step | |
| end | |
| self.current = ti | |
| end | |
| end | |
| function Playlist:wait(t) | |
| if t then | |
| self.current = self.current + t | |
| end | |
| end | |
| function Playlist:draw() | |
| if self.active then | |
| for k,e in ipairs(self.events) do | |
| if self.skip and e[1] < self.skip then | |
| table.remove(self.events,k) | |
| else | |
| if ElapsedTime - self.startat > e[1] and e[2]() then | |
| table.remove(self.events,k) | |
| end | |
| end | |
| end | |
| end | |
| end | |
| function Playlist:start() | |
| self.active = true | |
| self.running = true | |
| self.startat = ElapsedTime | |
| if self.skip then | |
| self.startat = self.startat - self.skip | |
| end | |
| end | |
| function Playlist:pause() | |
| self.active = false | |
| self.paused = true | |
| self.pausedat = ElapsedTime | |
| if self.pauseaction then | |
| self.pauseaction() | |
| end | |
| end | |
| function Playlist:resume() | |
| self.active = true | |
| self.paused = false | |
| if self.pausedat then | |
| self.startat = self.startat + ElapsedTime - self.pausedat | |
| end | |
| if self.resumeaction then | |
| self.resumeaction() | |
| end | |
| end | |
| function Playlist:stop() | |
| self.active = false | |
| self.running = false | |
| if self.lastaction then | |
| self.lastaction() | |
| end | |
| end | |
| return Playlist | |
| --]==] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --[==[ | |
| -- Rounded Rectangles | |
| --[[ | |
| This is an auxilliary function for drawing a rectangle with possibly | |
| curved cornders. The first four parameters specify the rectangle. | |
| The fifth is the radius of the corner rounding. The optional sixth is | |
| a way for specifying which corners should be rounded by passing a | |
| number between 0 and 15. The first bit corresponds to the lower-left | |
| corner and it procedes clockwise from there. | |
| --]] | |
| local __RRects = {} | |
| function RoundedRectangle(x,y,w,h,s,c,a) | |
| c = c or 0 | |
| w = w or 0 | |
| h = h or 0 | |
| if w < 0 then | |
| x = x + w | |
| w = -w | |
| end | |
| if h < 0 then | |
| y = y + h | |
| h = -h | |
| end | |
| w = math.max(w,2*s) | |
| h = math.max(h,2*s) | |
| a = a or 0 | |
| pushMatrix() | |
| translate(x,y) | |
| rotate(a) | |
| local label = table.concat({w,h,s,c},",") | |
| if __RRects[label] then | |
| __RRects[label]:setColors(fill()) | |
| __RRects[label]:draw() | |
| else | |
| local rr = mesh() | |
| local v = {} | |
| local ce = vec2(w/2,h/2) | |
| local n = 4 | |
| local o,dx,dy | |
| for j = 1,4 do | |
| dx = -1 + 2*(j%2) | |
| dy = -1 + 2*(math.floor(j/2)%2) | |
| o = ce + vec2(dx * (w/2 - s), dy * (h/2 - s)) | |
| if math.floor(c/2^(j-1))%2 == 0 then | |
| for i = 1,n do | |
| table.insert(v,o) | |
| table.insert(v,o + vec2(dx * s * math.cos((i-1) * math.pi/(2*n)), dy * s * math.sin((i-1) * math.pi/(2*n)))) | |
| table.insert(v,o + vec2(dx * s * math.cos(i * math.pi/(2*n)), dy * s * math.sin(i * math.pi/(2*n)))) | |
| end | |
| else | |
| table.insert(v,o) | |
| table.insert(v,o + vec2(dx * s,0)) | |
| table.insert(v,o + vec2(dx * s,dy * s)) | |
| table.insert(v,o) | |
| table.insert(v,o + vec2(0,dy * s)) | |
| table.insert(v,o + vec2(dx * s,dy * s)) | |
| end | |
| end | |
| rr.vertices = v | |
| rr:addRect(ce.x,ce.y,w,h-2*s) | |
| rr:addRect(ce.x,ce.y + (h-s)/2,w-2*s,s) | |
| rr:addRect(ce.x,ce.y - (h-s)/2,w-2*s,s) | |
| rr:setColors(fill()) | |
| rr:draw() | |
| __RRects[label] = rr | |
| end | |
| popMatrix() | |
| end | |
| cmodule.gexport { | |
| RoundedRectangle = RoundedRectangle | |
| } | |
| --]==] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --[==[ | |
| --[[ | |
| Functions for converting a touch to amd from the screen. | |
| --]] | |
| function converttouch(z,t,A) | |
| A = A or modelMatrix() * viewMatrix() * projectionMatrix() | |
| t = t or CurrentTouch or vec2(0,0) | |
| z = z or 0 | |
| local m = cofactor4(A) | |
| local ndc = {} | |
| local a | |
| ndc[1] = (t.x/WIDTH - .5)*2 | |
| ndc[2] = (t.y/HEIGHT - .5)*2 | |
| ndc[3] = z | |
| ndc[4] = 1 | |
| a = applymatrix4(ndc,m) | |
| if (a[4] == 0) then return end | |
| a = vec3(a[1], a[2], a[3])/a[4] | |
| return a | |
| end | |
| function getzlevel(v,A) | |
| A = A or modelMatrix() * viewMatrix() * projectionMatrix() | |
| v = v or vec3(0,0,0) | |
| local u = applymatrix4(vec4(v.x,v.y,v.z,1),A) | |
| if u[4] == 0 then return end | |
| return u[3]/u[4] | |
| end | |
| function __planetoscreen(o,u,v,A) | |
| A = A or modelMatrix() * viewMatrix() * projectionMatrix() | |
| o = o or vec3(0,0,0) | |
| u = u or vec3(1,0,0) | |
| v = v or vec3(0,1,0) | |
| -- promote to 4-vectors | |
| o = vec4(o.x,o.y,o.z,1) | |
| u = vec4(u.x,u.y,u.z,0) | |
| v = vec4(v.x,v.y,v.z,0) | |
| local oA, uA, vA | |
| oA = applymatrix4(o,A) | |
| uA = applymatrix4(u,A) | |
| vA = applymatrix4(v,A) | |
| return { uA[1], uA[2], uA[4], | |
| vA[1], vA[2], vA[4], | |
| oA[1], oA[2], oA[4]} | |
| end | |
| function screentoplane(t,o,u,v,A) | |
| A = A or modelMatrix() * viewMatrix() * projectionMatrix() | |
| o = o or vec3(0,0,0) | |
| u = u or vec3(1,0,0) | |
| v = v or vec3(0,1,0) | |
| t = t or CurrentTouch | |
| local m = __planetoscreen(o,u,v,A) | |
| m = cofactor3(m) | |
| local ndc = {} | |
| local a | |
| ndc[1] = (t.x/WIDTH - .5)*2 | |
| ndc[2] = (t.y/HEIGHT - .5)*2 | |
| ndc[3] = 1 | |
| a = applymatrix3(ndc,m) | |
| if (a[3] == 0) then return end | |
| a = vec2(a[1], a[2])/a[3] | |
| return o + a.x*u + a.y*v | |
| end | |
| function screennormal(t,A) | |
| A = A or modelMatrix() * viewMatrix() * projectionMatrix() | |
| t = t or CurrentTouch | |
| local u,v,w,x,y | |
| u = vec3(A[1],A[5],A[9]) | |
| v = vec3(A[2],A[6],A[10]) | |
| w = vec3(A[4],A[8],A[12]) | |
| x = (t.x/WIDTH - .5)*2 | |
| y = (t.y/HEIGHT - .5)*2 | |
| u = u - x*w | |
| v = v - y*w | |
| return u:cross(v) | |
| end | |
| cmodule.gexport { | |
| screennormal = screennormal, | |
| screentoplane = screentoplane, | |
| converttouch = converttouch, | |
| getzlevel = getzlevel | |
| } | |
| --]==] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --[==[ | |
| -- Utilities | |
| --[[ | |
| This is for little bits of code that are needed by more than one class but | |
| don't really belong to any one thing. | |
| --]] | |
| --[[ | |
| This is an auxilliary function for drawing a rectangle with possibly | |
| curved cornders. The first four parameters specify the rectangle. | |
| The fifth is the radius of the corner rounding. The optional sixth is | |
| a way for specifying which corners should be rounded by passing a | |
| number between 0 and 15. The first bit corresponds to the lower-left | |
| corner and it procedes clockwise from there. | |
| --]] | |
| local __RRects = {} | |
| function RoundedRectangle(x,y,w,h,s,c,a) | |
| c = c or 0 | |
| w = w or 0 | |
| h = h or 0 | |
| if w < 0 then | |
| x = x + w | |
| w = -w | |
| end | |
| if h < 0 then | |
| y = y + h | |
| h = -h | |
| end | |
| w = math.max(w,2*s) | |
| h = math.max(h,2*s) | |
| a = a or 0 | |
| pushMatrix() | |
| translate(x,y) | |
| rotate(a) | |
| local label = table.concat({w,h,s,c},",") | |
| if __RRects[label] then | |
| __RRects[label]:setColors(fill()) | |
| __RRects[label]:draw() | |
| else | |
| local rr = mesh() | |
| local v = {} | |
| local ce = vec2(w/2,h/2) | |
| local n = 4 | |
| local o,dx,dy | |
| for j = 1,4 do | |
| dx = -1 + 2*(j%2) | |
| dy = -1 + 2*(math.floor(j/2)%2) | |
| o = ce + vec2(dx * (w/2 - s), dy * (h/2 - s)) | |
| if math.floor(c/2^(j-1))%2 == 0 then | |
| for i = 1,n do | |
| table.insert(v,o) | |
| table.insert(v,o + vec2(dx * s * math.cos((i-1) * math.pi/(2*n)), dy * s * math.sin((i-1) * math.pi/(2*n)))) | |
| table.insert(v,o + vec2(dx * s * math.cos(i * math.pi/(2*n)), dy * s * math.sin(i * math.pi/(2*n)))) | |
| end | |
| else | |
| table.insert(v,o) | |
| table.insert(v,o + vec2(dx * s,0)) | |
| table.insert(v,o + vec2(dx * s,dy * s)) | |
| table.insert(v,o) | |
| table.insert(v,o + vec2(0,dy * s)) | |
| table.insert(v,o + vec2(dx * s,dy * s)) | |
| end | |
| end | |
| rr.vertices = v | |
| rr:addRect(ce.x,ce.y,w,h-2*s) | |
| rr:addRect(ce.x,ce.y + (h-s)/2,w-2*s,s) | |
| rr:addRect(ce.x,ce.y - (h-s)/2,w-2*s,s) | |
| rr:setColors(fill()) | |
| rr:draw() | |
| __RRects[label] = rr | |
| end | |
| popMatrix() | |
| end | |
| function OldRoundedRectangle(x,y,w,h,r,c) | |
| if not c then | |
| c = 0 | |
| end | |
| if w < 0 then | |
| x = x + w | |
| w = -w | |
| end | |
| if h < 0 then | |
| y = y + h | |
| h = -h | |
| end | |
| pushStyle() | |
| strokeWidth(-1) | |
| ellipseMode(RADIUS) | |
| rectMode(RADIUS) | |
| CircleOrSquare(x+r,y+r,r,c%2) | |
| CircleOrSquare(x+r,y+h-r,r,math.floor(c/2)%2) | |
| CircleOrSquare(x+w-r,y+h-r,r,math.floor(c/4)%2) | |
| CircleOrSquare(x+w-r,y+r,r,math.floor(c/8)%2) | |
| rectMode(CORNER) | |
| rect(x+r,y,w - 2 * r,h) | |
| rect(x,y + r,w,h - 2 * r) | |
| popStyle() | |
| end | |
| --[[ | |
| This is for rounding or not rounding the corners. | |
| --]] | |
| function CircleOrSquare(x,y,r,c) | |
| if c == 0 then | |
| ellipse(x,y,r) | |
| else | |
| rect(x,y,r,r) | |
| end | |
| end | |
| function Ordinal(n) | |
| local k = n%10 | |
| local th = "th" | |
| if k == 1 then | |
| th = "st" | |
| elseif k == 2 then | |
| th = "nd" | |
| elseif k == 3 then | |
| th = "rd" | |
| end | |
| return n .. th | |
| end | |
| function Regression(t) | |
| local n, xy, x, y, xx, yy = 0,0,0,0,0,0 | |
| for k,v in ipairs(t) do | |
| n = n + 1 | |
| xy = xy + v.x*v.y | |
| x = x + v.x | |
| y = y + v.y | |
| xx = xx + v.x*v.x | |
| yy = yy + v.y*v.y | |
| end | |
| local d = n*xx - x*x | |
| if d == 0 then | |
| return false,false,Matrix({{0,0},{0,0}}) | |
| end | |
| local matrix | |
| if Matrix then | |
| matrix = Matrix({{xx,x},{x,n}}) | |
| end | |
| return (n*xy - x*y)/d, | |
| (-x*xy + xx*y)/d, | |
| matrix, | |
| (n*xy -x*y)^2/((n*xx-x*x)*(n*yy-y*y)) | |
| end | |
| --[[ | |
| Vertex ordering: | |
| 1 -- 2 | |
| | | | |
| 3 -- 4 | |
| --]] | |
| function addQuad(t) | |
| local m = t.mesh | |
| local n = t.position or 0 | |
| if n > m.size - 12 then | |
| m:resize(n + 300) | |
| end | |
| local v = t.vertices | |
| for k,l in ipairs({1,2,3,2,3,4}) do | |
| m:vertex(n+k,v[l][1]) | |
| if v[l][2] then | |
| m:color(n+k,v[l][2]) | |
| end | |
| if v[l][3] then | |
| m:texCoord(n+k,v[l][3]) | |
| end | |
| end | |
| return n + 6 | |
| end | |
| function addTriangle(t) | |
| local m = t.mesh | |
| local n = t.position or 0 | |
| if n > m.size - 12 then | |
| m:resize(n + 300) | |
| end | |
| local v = t.vertices | |
| for k,l in ipairs({1,2,3}) do | |
| m:vertex(n+k,v[l][1]) | |
| m:color(n+k,v[l][2]) | |
| end | |
| return n + 3 | |
| end | |
| --[[ | |
| Adds a rounded rectangle to an existing mesh | |
| --]] | |
| function addRoundedRect(t) | |
| local m = t.mesh | |
| local x = t.x | |
| local y = t.y | |
| local w = t.width or 0 | |
| local h = t.height or 0 | |
| local s = t.radius or 10 | |
| local c = t.corners or 0 | |
| local a = t.anchor | |
| local fc = t.colour or fill() | |
| if a then | |
| x,y = RectAnchorAt(x,y,w,h,a) | |
| end | |
| local v = {} | |
| local nv = 0 | |
| local ce = vec2(x + w/2,y + h/2) | |
| local n = 4 | |
| local o,dx,dy | |
| for j = 1,4 do | |
| dx = -1 + 2*(j%2) | |
| dy = -1 + 2*(math.floor(j/2)%2) | |
| o = ce + vec2(dx * (w/2 - s), dy * (h/2 - s)) | |
| if math.floor(c/2^(j-1))%2 == 0 then | |
| for i = 1,n do | |
| table.insert(v,o) | |
| table.insert(v,o + vec2(dx * s * math.cos((i-1) * math.pi/(2*n)), dy * s * math.sin((i-1) * math.pi/(2*n)))) | |
| table.insert(v,o + vec2(dx * s * math.cos(i * math.pi/(2*n)), dy * s * math.sin(i * math.pi/(2*n)))) | |
| end | |
| nv = nv + 3*n | |
| else | |
| table.insert(v,o) | |
| table.insert(v,o + vec2(dx * s,0)) | |
| table.insert(v,o + vec2(dx * s,dy * s)) | |
| table.insert(v,o) | |
| table.insert(v,o + vec2(0,dy * s)) | |
| table.insert(v,o + vec2(dx * s,dy * s)) | |
| nv = nv + 6 | |
| end | |
| end | |
| local nrv = m.size | |
| m:resize(nrv + nv) | |
| for k,ve in ipairs(v) do | |
| m:vertex(nrv + k, ve) | |
| m:color(nrv+k,fc) | |
| end | |
| local ri = m:addRect(ce.x,ce.y,w,h-2*s) | |
| m:setRectColor(ri,fc) | |
| ri = m:addRect(ce.x,ce.y + (h-s)/2,w-2*s,s) | |
| m:setRectColor(ri,fc) | |
| ri = m:addRect(ce.x,ce.y - (h-s)/2,w-2*s,s) | |
| m:setRectColor(ri,fc) | |
| end | |
| function ApplyAffine(m,v) | |
| if v then | |
| return v.x*m[1] + v.y*m[2] + m[3] | |
| else | |
| applyMatrix(matrix( | |
| m[1].x, m[1].y, 0, 0, | |
| m[2].x, m[2].y, 0, 0, | |
| 0,0,1,0, | |
| m[3].x, m[3].y, 0, 1 | |
| )) | |
| end | |
| end | |
| function USRotateCW(v) | |
| return ApplyAffine({vec2(0,-1),vec2(1,0),vec2(0,1)},v) | |
| end | |
| function USRotateCCW(v) | |
| return ApplyAffine({vec2(0,1),vec2(-1,0),vec2(1,0)},v) | |
| end | |
| function USReflectV(v) | |
| return ApplyAffine({vec2(-1,0),vec2(0,1),vec2(1,0)},v) | |
| end | |
| function USReflectH(v) | |
| return ApplyAffine({vec2(1,0),vec2(0,-1),vec2(0,1)},v) | |
| end | |
| USCoordinates = {} | |
| USCoordinates[PORTRAIT] = {vec2(1,0),vec2(0,1),vec2(0,0)} | |
| USCoordinates[PORTRAIT_UPSIDE_DOWN] = {vec2(-1,0),vec2(0,-1),vec2(1,1)} | |
| USCoordinates[LANDSCAPE_LEFT] = {vec2(0,-1),vec2(1,0),vec2(0,1)} | |
| USCoordinates[LANDSCAPE_RIGHT] = {vec2(0,1),vec2(-1,0),vec2(1,0)} | |
| function USOrientation(o,v) | |
| return ApplyAffine(USCoordinates[o],v) | |
| end | |
| function getLength(l) | |
| local n = tonumber(l) | |
| if n then | |
| return n | |
| end | |
| local i,j,m,u = string.find(l,"^(%d*)(%D*)$") | |
| if i then | |
| if u == "px" or u == "pcx" then | |
| return m | |
| elseif u == "pt" then | |
| return m * 3.653 | |
| elseif u == "in" then | |
| return m * 264 | |
| elseif u == "cm" then | |
| return m * 670.56 | |
| elseif u == "mm" then | |
| return m * 6705.6 | |
| elseif u == "m" then | |
| return m * 67.056 | |
| elseif u == "em" then | |
| local t = fontMetrics() | |
| return m * t.size | |
| elseif u == "en" then | |
| local t = fontMetrics() | |
| return m * t.size/2 | |
| elseif u == "ex" then | |
| local t = fontMetrics() | |
| return m * t.xHeight | |
| elseif u == "lh" then | |
| local _,h = textSize("x") | |
| return m * h | |
| else | |
| return nil | |
| end | |
| end | |
| return nil | |
| end | |
| function evalLength(s) | |
| if type(s) == "function" then | |
| s = s() | |
| end | |
| s = string.gsub(s,"(%d+%a+)", | |
| function(n) return getLength(n) or n end) | |
| s = "local s = " .. s .. " return s" | |
| local f = loadstring(s) | |
| s = f() | |
| return s | |
| end | |
| function TriangleArea(a,b,c) | |
| return math.abs( | |
| a:dot(b:rotate90()) | |
| + b:dot(c:rotate90()) | |
| + c:dot(a:rotate90()) | |
| )/2 | |
| end | |
| function converttouch(z,t,A) | |
| A = A or modelMatrix() * viewMatrix() * projectionMatrix() | |
| t = t or CurrentTouch or vec2(0,0) | |
| z = z or 0 | |
| local m = cofactor4(A) | |
| local ndc = {} | |
| local a | |
| ndc[1] = (t.x/WIDTH - .5)*2 | |
| ndc[2] = (t.y/HEIGHT - .5)*2 | |
| ndc[3] = z | |
| ndc[4] = 1 | |
| a = applymatrix4(ndc,m) | |
| if (a[4] == 0) then return end | |
| a = vec3(a[1], a[2], a[3])/a[4] | |
| return a | |
| end | |
| function getzlevel(v,A) | |
| A = A or modelMatrix() * viewMatrix() * projectionMatrix() | |
| v = v or vec3(0,0,0) | |
| local u = applymatrix4(vec4(v.x,v.y,v.z,1),A) | |
| if u[4] == 0 then return end | |
| return u[3]/u[4] | |
| end | |
| function applymatrix4(v,m) | |
| local u = {} | |
| u[1] = m[1]*v[1] + m[5]*v[2] + m[09]*v[3] + m[13]*v[4] | |
| u[2] = m[2]*v[1] + m[6]*v[2] + m[10]*v[3] + m[14]*v[4] | |
| u[3] = m[3]*v[1] + m[7]*v[2] + m[11]*v[3] + m[15]*v[4] | |
| u[4] = m[4]*v[1] + m[8]*v[2] + m[12]*v[3] + m[16]*v[4] | |
| return u | |
| end | |
| function cofactor4(m) | |
| local rm = matrix() | |
| local sgn,l | |
| local fm = {} | |
| for k=1,16 do | |
| fm = {} | |
| l = math.floor((k-1)/4) + 1 + 4*((k-1)%4) | |
| sgn = (-1)^(math.floor((k-1)/4))*(-1)^((k-1)%4) | |
| for j=1,16 do | |
| if j%4 ~= k%4 | |
| and math.floor((j-1)/4) ~= math.floor((k-1)/4) | |
| then | |
| table.insert(fm,m[j]) | |
| end | |
| end | |
| rm[l] = sgn*Det3(fm) | |
| end | |
| return rm | |
| end | |
| function Det3(t) | |
| return t[1]*t[5]*t[9] | |
| + t[2]*t[6]*t[7] | |
| + t[3]*t[4]*t[8] | |
| - t[3]*t[5]*t[7] | |
| - t[2]*t[4]*t[9] | |
| - t[1]*t[6]*t[8] | |
| end | |
| function applymatrix3(v,m) | |
| local u = {} | |
| u[1] = m[1]*v[1] + m[4]*v[2] + m[7]*v[3] | |
| u[2] = m[2]*v[1] + m[5]*v[2] + m[8]*v[3] | |
| u[3] = m[3]*v[1] + m[6]*v[2] + m[9]*v[3] | |
| return u | |
| end | |
| function cofactor3(m) | |
| local rm = {} | |
| local sgn,l | |
| local fm = {} | |
| for k=1,9 do | |
| fm = {} | |
| l = math.floor((k-1)/3) + 1 + 3*((k-1)%3) | |
| sgn = (-1)^(math.floor((k-1)/3))*(-1)^((k-1)%3) | |
| for j=1,9 do | |
| if j%3 ~= k%3 | |
| and math.floor((j-1)/3) ~= math.floor((k-1)/3) | |
| then | |
| table.insert(fm,m[j]) | |
| end | |
| end | |
| rm[l] = sgn*Det2(fm) | |
| end | |
| return rm | |
| end | |
| function Det2(t) | |
| return t[1]*t[4] - t[2]*t[3] | |
| end | |
| function __planetoscreen(o,u,v,A) | |
| A = A or modelMatrix() * viewMatrix() * projectionMatrix() | |
| o = o or vec3(0,0,0) | |
| u = u or vec3(1,0,0) | |
| v = v or vec3(0,1,0) | |
| -- promote to 4-vectors | |
| o = vec4(o.x,o.y,o.z,1) | |
| u = vec4(u.x,u.y,u.z,0) | |
| v = vec4(v.x,v.y,v.z,0) | |
| local oA, uA, vA | |
| oA = applymatrix4(o,A) | |
| uA = applymatrix4(u,A) | |
| vA = applymatrix4(v,A) | |
| return { uA[1], uA[2], uA[4], | |
| vA[1], vA[2], vA[4], | |
| oA[1], oA[2], oA[4]} | |
| end | |
| function screentoplane(t,o,u,v,A) | |
| A = A or modelMatrix() * viewMatrix() * projectionMatrix() | |
| o = o or vec3(0,0,0) | |
| u = u or vec3(1,0,0) | |
| v = v or vec3(0,1,0) | |
| t = t or CurrentTouch | |
| local m = __planetoscreen(o,u,v,A) | |
| m = cofactor3(m) | |
| local ndc = {} | |
| local a | |
| ndc[1] = (t.x/WIDTH - .5)*2 | |
| ndc[2] = (t.y/HEIGHT - .5)*2 | |
| ndc[3] = 1 | |
| a = applymatrix3(ndc,m) | |
| if (a[3] == 0) then return end | |
| a = vec2(a[1], a[2])/a[3] | |
| return o + a.x*u + a.y*v | |
| end | |
| function screennormal(t,A) | |
| A = A or modelMatrix() * viewMatrix() * projectionMatrix() | |
| t = t or CurrentTouch | |
| local u,v,w,x,y | |
| u = vec3(A[1],A[5],A[9]) | |
| v = vec3(A[2],A[6],A[10]) | |
| w = vec3(A[4],A[8],A[12]) | |
| x = (t.x/WIDTH - .5)*2 | |
| y = (t.y/HEIGHT - .5)*2 | |
| u = u - x*w | |
| v = v - y*w | |
| return u:cross(v) | |
| end | |
| function AddPlank(t) | |
| local w = t.width | |
| local h = t.height | |
| local d = t.depth | |
| local o = t.origin | |
| local cube = {} | |
| local j,k,l | |
| for i=0,7 do | |
| j = 2*(i%2)-1 | |
| k = 2*(math.floor(i/2)%2)-1 | |
| l = 2*(math.floor(i/4)%2)-1 | |
| table.insert(cube, o + j*w + k*h + l* d) | |
| end | |
| return AddCube({ | |
| vertices = t.vertices, | |
| colours = t.colours, | |
| light = t.light, | |
| cube = cube, | |
| colour = t.colour or Colour.x11.Burlywood3 | |
| }) | |
| end | |
| function AddSlab(t) | |
| local sc = t.startCentre | |
| local sh = t.startHeight | |
| local sw = t.startWidth | |
| local ec = t.endCentre | |
| local eh = t.endHeight | |
| local ew = t.endWidth | |
| local cube = {} | |
| local j,k | |
| for i=0,3 do | |
| j = 2*(i%2)-1 | |
| k = 2*(math.floor(i/2)%2)-1 | |
| table.insert(cube,sc + j*sh + k*sw) | |
| table.insert(cube,ec + j*eh + k*ew) | |
| end | |
| return AddCube({ | |
| vertices = t.vertices, | |
| colours = t.colours, | |
| light = t.light, | |
| cube = cube, | |
| colour = t.colour or Colour.x11.Burlywood3 | |
| }) | |
| end | |
| function AddHalfTube(t) | |
| local r = t.radius | |
| local b = { | |
| {t.startCentre,t.startWidth,t.startHeight}, | |
| {t.endCentre,t.endWidth,t.endHeight} | |
| } | |
| local vertices = t.vertices | |
| local colours = t.colours | |
| local c = t.colour or Colour.svg.DarkSlateBlue | |
| local l = t.light:normalize() | |
| local n = t.number or 36 | |
| local step = math.pi/n | |
| local ang,pang,lc,ver | |
| for i = 1,n do | |
| ang = i*step | |
| pang = (i-1)*step | |
| for k,v in ipairs({ | |
| {1,pang}, | |
| {1,ang}, | |
| {2,ang}, | |
| {2,ang}, | |
| {1,pang}, | |
| {2,pang} | |
| }) do | |
| ver = math.cos(v[2]) * b[v[1]][2] + math.sin(v[2]) * b[v[1]][3] | |
| table.insert(vertices,b[v[1]][1] + ver) | |
| lc = l:dot(ver) | |
| table.insert(colours,Colour.shade(c,50 + 25*lc)) | |
| end | |
| end | |
| return vertices, colours | |
| end | |
| function AddTube(t) | |
| local r = t.radius | |
| local b = { | |
| {t.startCentre,t.startWidth,t.startHeight,t.startTexture}, | |
| {t.endCentre,t.endWidth,t.endHeight,t.endTexture} | |
| } | |
| local vertices = t.vertices | |
| local colours = t.colours | |
| local texcoords = t.texCoords | |
| local normals = t.normals | |
| local c = t.colour or Colour.svg.DarkSlateBlue | |
| local l = t.light | |
| if l then | |
| l = l:normalize() | |
| end | |
| local n = t.number or 36 | |
| local step = 2*math.pi/n | |
| local ang,pang,lc,ver | |
| for i = 1,n do | |
| ang = i*step | |
| pang = (i-1)*step | |
| for k,v in ipairs({ | |
| {1,pang}, | |
| {1,ang}, | |
| {2,ang}, | |
| {2,ang}, | |
| {1,pang}, | |
| {2,pang} | |
| }) do | |
| ver = math.cos(v[2]) * b[v[1]][2] + math.sin(v[2]) * b[v[1]][3] | |
| table.insert(vertices,b[v[1]][1] + ver) | |
| if l then | |
| lc = l:dot(ver) | |
| table.insert(colours,Colour.shade(c,50 + 25*lc)) | |
| else | |
| table.insert(colours,c) | |
| end | |
| if texcoords then | |
| table.insert(texcoords, | |
| vec2(b[v[1]][4],v[2]/(2*math.pi))) | |
| end | |
| if normals then | |
| table.insert(normals, | |
| ver:normalize()) | |
| end | |
| end | |
| end | |
| return vertices, colours, texcoords, normals | |
| end | |
| -- cube faces are in binary order: 000, 001, 010, 011 etc | |
| local CubeFaces = { | |
| {1,2,3,4}, | |
| {5,7,6,8}, | |
| {1,5,2,6}, | |
| {3,4,7,8}, | |
| {2,6,4,8}, | |
| {1,3,5,7} | |
| } | |
| function AddCube(t) | |
| local cube = t.cube | |
| local vertices = t.vertices or {} | |
| local colours = t.colours or {} | |
| local normals = t.normals or {} | |
| local c = t.colour or Colour.x11.Burlywood3 | |
| local l = t.light:normalize() | |
| local faces = t.faces or CubeFaces | |
| local lc,n | |
| for k,v in ipairs(faces) do | |
| n = (cube[v[3]] - cube[v[1]]):cross(cube[v[2]] - cube[v[1]]) | |
| if n ~= vec3(0,0,0) then | |
| n = n:normalize() | |
| lc = n:dot(l) | |
| end | |
| for i,u in ipairs({1,2,3,2,3,4}) do | |
| table.insert(vertices,cube[v[u]]) | |
| table.insert(normals,n) | |
| table.insert(colours, | |
| Colour.shade(c,75 + 25*lc) | |
| ) | |
| end | |
| end | |
| return vertices,colours,normals | |
| end | |
| function AddJewel(t) | |
| local o = t.origin | |
| local a = SO3(t.axis,vec3(0,0,1)) | |
| local n = t.sides | |
| local la = t.axis:len() | |
| for i = 1,3 do | |
| a[i] = la*a[i] | |
| end | |
| local vertices = t.vertices or {} | |
| local colours = t.colours or {} | |
| local clr = t.colour or Colour.svg.IndianRed | |
| local l = t.light:normalize() | |
| local th = math.pi/n | |
| local cs = math.cos(th) | |
| local sn = math.sin(th) | |
| local h = (1 - cs)/(1 + cs) | |
| local nh = 1/(1+h) | |
| local nhl = 1/math.sqrt(1 + nh^2) | |
| local k,b,c,d,nml,cl,nv | |
| b = a[2] | |
| c = cs*a[2] + sn*a[3] | |
| d = -sn*a[2] + cs*a[3] | |
| nv = 0 | |
| for i = 1,2*n do | |
| k = 2*(i%2) - 1 | |
| for j = -1,1,2 do | |
| table.insert(vertices,o + j*a[1]) | |
| table.insert(vertices,o + h*k*a[1] + b) | |
| table.insert(vertices,o - h*k*a[1] + c) | |
| nml = j*nh*a[1] + .5*(1 - j*k)*b + .5*(1 + j*k)*c | |
| cl = nml:dot(l)/nhl | |
| for m=1,3 do | |
| table.insert(colours,Colour.shade(clr,75 + 25*cl)) | |
| end | |
| nv = nv + 3 | |
| end | |
| b = c | |
| c = cs*c + sn*d | |
| d = -sn*b + cs*d | |
| end | |
| return vertices,colours,nv | |
| end | |
| function TrackPoints(a) | |
| a = a or {} | |
| local pts = a.points or {} | |
| local t = a.start or 0 | |
| local r = a.step or .1 | |
| r = r*r | |
| local s = a.delta or .1 | |
| local f = a.pathFunction or function(q) return q*vec3(1,0,0) end | |
| local nf = a.normalFunction or function(q) return vec3(0,1,0) end | |
| local b = a.finish or 1 | |
| local tpt = f(t) | |
| table.insert(pts,{tpt, | |
| tangent({delta = s, pathFunction = f, time = t}), | |
| nf(t),t}) | |
| local dis | |
| local p | |
| while t < b do | |
| dis = 0 | |
| while dis < r do | |
| t = t + s | |
| p = f(t) | |
| dis = dis + p:distSqr(tpt) | |
| tpt = p | |
| end | |
| if t > b then | |
| t = b | |
| p = f(b) | |
| end | |
| table.insert(pts,{p, | |
| tangent({delta = s, pathFunction = f, time = t}), | |
| nf(t),t}) | |
| tpt = p | |
| end | |
| return pts | |
| end | |
| function AddStar(t) | |
| local o = t.origin | |
| local s = t.size | |
| local l = t.light:normalize()/(math.sqrt(3)) | |
| local vertices = t.vertices or {} | |
| local colours = t.colours or {} | |
| local b = RandomBasisR3() | |
| local v,n,c | |
| local bb = {} | |
| for i=0,7 do | |
| bb[1] = 2*(i%2)-1 | |
| bb[2] = 2*(math.floor(i/2)%2)-1 | |
| bb[3] = 2*(math.floor(i/4)%2)-1 | |
| v = bb[1]*b[1] + bb[2]*b[2] + bb[3]*b[3] | |
| n = math.abs(v:dot(l)) | |
| c = Colour.shade(Colour.x11["LemonChiffon" .. math.random(1,4)], 70+n*30) | |
| for m=1,3 do | |
| table.insert(colours,c) | |
| table.insert(vertices,o+s*(v - 2*bb[m]*b[m])) | |
| end | |
| end | |
| return vertices,colours | |
| end | |
| function tangent(a) | |
| local s = a.delta/2 or .1 | |
| local f = a.pathFunction or function(q) return q*vec3(1,0,0) end | |
| local t = a.time or 0 | |
| local u = f(t-s) | |
| local v = f(t+s) | |
| return (v-u)/(2*s) | |
| end | |
| local Tracks = {} | |
| function Tracks.torus(p,q) | |
| local innerRa = 10 | |
| local innerRb = 10 | |
| local outerR = 30 | |
| local trackFunction = function(t) | |
| local it = p*t*2*math.pi | |
| local ot = q*t*2*math.pi | |
| return vec3( | |
| (outerR + innerRb*math.cos(it))*math.cos(ot), | |
| innerRa*math.sin(it), | |
| (outerR + innerRb*math.cos(it))*math.sin(ot) | |
| ) | |
| end | |
| local trackNormal = function(t) | |
| local it = p*t*2*math.pi | |
| local ot = q*t*2*math.pi | |
| return vec3( | |
| innerRa*math.cos(it)*math.cos(ot), | |
| innerRb*math.sin(it), | |
| innerRa*math.cos(it)*math.sin(ot) | |
| ) | |
| end | |
| local coreFunction = function(t) | |
| local ot = q*t*2*math.pi | |
| return vec3( | |
| outerR*math.cos(ot), | |
| 0, | |
| outerR*math.sin(ot) | |
| ) | |
| end | |
| local maxHeight = innerRa | |
| local minHeight = -innerRa | |
| return trackFunction, trackNormal, maxHeight, minHeight | |
| end | |
| function Tracks.mobius() | |
| local r = 30 | |
| local trackFunction = function(t) | |
| local a = 2*math.pi*t | |
| return vec3(r*math.cos(a),0,r*math.sin(a)) | |
| end | |
| local trackNormal = function(t) | |
| local a = math.pi*t | |
| return vec3( | |
| math.sin(a)*math.cos(2*a), | |
| math.cos(a), | |
| math.sin(a)*math.sin(2*a)) | |
| end | |
| return trackFunction,trackNormal,0.5,-0.5 | |
| end | |
| function Tracks.loop(p,q,r,h) | |
| local r = r or 30 | |
| local h = h or 10 | |
| local w = vec3(0,50,0) | |
| local trackFunction = function(t) | |
| local a = 2*math.pi*t | |
| return vec3( | |
| r*math.cos(a), | |
| h*math.sin(p*a), | |
| r*math.sin(q*a)) | |
| end | |
| local trackNormal = function(t) | |
| return w - trackFunction(t) | |
| end | |
| return trackFunction,trackNormal,h,-h | |
| end | |
| function RandomVec3() | |
| local th = 2*math.pi*math.random() | |
| local z = 2*math.random() - 1 | |
| local r = math.sqrt(1 - z*z) | |
| return vec3(r*math.cos(th),r*math.sin(th),z) | |
| end | |
| function RandomBasisR3() | |
| local th = 2*math.pi*math.random() | |
| local cth = math.cos(th) | |
| local sth = math.sin(th) | |
| local a = vec3(cth,sth,0) | |
| local b = vec3(-sth,cth,0) | |
| local c = vec3(0,0,1) | |
| local v = RandomVec3() | |
| a = a - 2*v:dot(a)*v | |
| b = b - 2*v:dot(b)*v | |
| c = c - 2*v:dot(c)*v | |
| return {a,b,c} | |
| end | |
| function SO3(u,v) | |
| if u == vec3(0,0,0) then | |
| if v == vec3(0,0,0) then | |
| return {vec3(1,0,0),vec3(0,1,0),vec3(0,0,1)} | |
| end | |
| u,v = v,u | |
| end | |
| if u:cross(v) == vec3(0,0,0) then | |
| if u.x == 0 and u.y == 0 then | |
| v = vec3(1,0,0) | |
| else | |
| v = vec3(u.y,-u.x,0) | |
| end | |
| end | |
| local t = GramSchmidt({u,v}) | |
| t[3] = t[1]:cross(t[2]) | |
| return t | |
| end | |
| function GramSchmidt(t) | |
| local o = {} | |
| local w | |
| for k,v in ipairs(t) do | |
| w = v | |
| for l,u in ipairs(o) do | |
| w = w - w:dot(u)*u | |
| end | |
| if w ~= vec3(0,0,0) then | |
| w = w:normalize() | |
| table.insert(o,w) | |
| end | |
| end | |
| return o | |
| end | |
| local Boolean = {} | |
| function Boolean.readData(t,k,b) | |
| local f | |
| if t == "global" then | |
| f = readGlobalData | |
| elseif t == "project" then | |
| f = readProjectData | |
| else | |
| f = readLocalData | |
| end | |
| local bol = f(k) | |
| if bol then | |
| if bol == 0 then | |
| return false | |
| else | |
| return true | |
| end | |
| else | |
| return b | |
| end | |
| end | |
| function Boolean.saveData(t,k,b) | |
| local f | |
| if t == "global" then | |
| f = saveGlobalData | |
| elseif t == "project" then | |
| f = saveProjectData | |
| else | |
| f = saveLocalData | |
| end | |
| if b then | |
| f(k,1) | |
| else | |
| f(k,0) | |
| end | |
| end | |
| cmodule.gexport { | |
| RoundedRectangle = RoundedRectangle, | |
| CircleOrSquare = CircleOrSquare, | |
| Ordinal = Ordinal, | |
| Regression = Regression, | |
| addQuad = addQuad, | |
| addTriangle = addTriangle, | |
| addRoundedRect = addRoundedRect, | |
| ApplyAffine = ApplyAffine, | |
| USRotateCW = USRotateCW, | |
| USRotateCCW = USRotateCCW, | |
| USReflectV = USReflectV, | |
| USReflectH = USReflectH, | |
| USOrientation = USOrientation, | |
| getLength = getLength, | |
| evalLength = evalLength, | |
| TriangleArea = TriangleArea, | |
| converttouch = converttouch, | |
| getzlevel = getzlevel, | |
| applymatrix4 = applymatrix4, | |
| cofactor4 = cofactor4, | |
| Det3 = Det3, | |
| applymatrix3 = applymatrix3, | |
| cofactor3 = cofactor3, | |
| Det2 = Det2, | |
| screentoplane = screentoplane, | |
| screennormal = screennormal, | |
| AddPlank = AddPlank, | |
| AddSlab = AddSlab, | |
| AddHalfTube = AddHalfTube, | |
| AddTube = AddTube, | |
| AddCube = AddCube, | |
| AddJewel = AddJewel, | |
| TrackPoints = TrackPoints, | |
| AddStar = AddStar, | |
| tangent = tangent, | |
| Tracks = Tracks, | |
| RandomVec3 = RandomVec3, | |
| RandomBasisR3 = RandomBasisR3, | |
| SO3 = SO3, | |
| GramSchmidt = GramSchmidt, | |
| Boolean = Boolean | |
| } | |
| --]==] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment