Created
February 7, 2014 06:57
-
-
Save JMV38/8858365 to your computer and use it in GitHub Desktop.
Codea Project Gist Created with AutoGist
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
| AutoGist Tab Order Version: 2.2.8 | |
| ------------------------------ | |
| This file should not be included in the Codea project. | |
| #Main | |
| #Convert | |
| #ObjectClassForTest |
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
| Convert = class() | |
| -- this class exposes save() and load() function to | |
| -- > convert a table to an image on the disk | |
| -- > read an image from disk and add its elements to a table object | |
| -- Only the table elements of following types can be saved or read (others are ignored) | |
| -- "{color}" means "a table of 'color' elements with integer indexation" | |
| function Convert:supported(typ) | |
| local ans = false | |
| if typ=="string" then ans = true | |
| elseif typ=="number" then ans = true | |
| elseif typ=="image" then ans = true | |
| elseif typ=="{color}"then ans = true | |
| elseif typ=="{vec3}" then ans = true | |
| elseif typ=="{vec2}" then ans = true | |
| elseif typ=="matrix" then ans = true | |
| elseif typ=="{matrix}" then ans = true | |
| elseif typ=="mesh" then ans = true | |
| end | |
| return ans | |
| end | |
| function Convert:init() | |
| end | |
| -- local functions to be faster | |
| local insert = table.insert | |
| local floor = math.floor | |
| -- print txt..t if debug is true | |
| function debugPrint(debug,txt,t) | |
| if debug then | |
| local str = "" | |
| if type(t)=="table" then str ="{"..tostring(t[1])..",... }" | |
| elseif t~=nil then str = tostring(t) | |
| end | |
| print(txt..str) | |
| end | |
| end | |
| -- ********************************************** | |
| -- object <=> image on disk | |
| -- ********************************************** | |
| -- table obj is saved to image 'name' | |
| function Convert:save(obj,name,debug) | |
| local img = self:pushObject01(obj,debug) | |
| local size = floor(img.width * img.height /2048 /2048 /2 *100) | |
| debugPrint(debug,"object size = "..size.."% of max size") | |
| self:saveImage(name, img) | |
| return size | |
| end | |
| -- image 'name' is interpreted as a table and its tags forced to obj | |
| function Convert:load(obj,name,debug) | |
| local img = self:readImage(name) | |
| local obj1 = self:popObject01(img) | |
| local txt1,txt2 | |
| for tag,v in pairs(obj1) do | |
| debugPrint(debug,"initial : obj."..tag.." = ",obj[tag]) | |
| obj[tag] = v | |
| debugPrint(debug,"final : obj."..tag.." = ",v) | |
| end | |
| end | |
| -- these function have been introduced because IOS can save only pre-multiplied images, | |
| -- so to have no problems alpha must be 255 | |
| -- => i've split (r.g.b.a) in (r.g.0.255) and (b.a.0.255) | |
| function Convert:saveImage(name,img) | |
| local w,h = img.width, img.height | |
| local x,y,r,g,b,a | |
| local out = image(w,h*2) | |
| for x=1,w do for y=1,h do | |
| r,g,b,a = img:get(x,y) | |
| out:set(x,y*2-1,r,g,0,255) | |
| out:set(x,y*2 ,b,a,0,255) | |
| end end | |
| saveImage("Documents:"..name,out) | |
| end | |
| function Convert:readImage(name) | |
| local img = readImage("Documents:"..name) | |
| local w,h = img.width, img.height | |
| local x,y,r,g,b,a,_ | |
| local out = image(w,h/2) | |
| for x=1,w do for y=1,h/2 do | |
| r,g,_,_ = img:get(x,y*2-1) | |
| b,a,_,_ = img:get(x,y*2) | |
| out:set(x,y,r,g,b,a) | |
| end end | |
| return out | |
| end | |
| -- ********************************************** | |
| -- object <=> image | |
| -- ********************************************** | |
| function Convert:pushObject01(obj,debug) | |
| debugPrint(debug,".....Start of pushObject01.....") | |
| local header = {} | |
| header.id = "JMV38-3d-object" | |
| header.version = 1 | |
| -- put everything in a table | |
| local t ={} | |
| self:pushTag("id",header,t) | |
| debugPrint(debug,"pushed : header.".."id".." = ",header.id) | |
| self:pushTag("version",header,t) | |
| debugPrint(debug,"pushed : header.".."version".." = ",header.version) | |
| local i,v | |
| for i,v in pairs(obj) do | |
| self:pushTag(i,obj,t) | |
| debugPrint(debug,"pushed : obj."..i.." = ",tostring(v)) | |
| end | |
| -- 1 more pixel at 0 to indicate it is finished (and avoid image overflow) | |
| insert(t, self:intToColor(0) ) | |
| -- convert to an image and return it | |
| return self:tableToImage(t) | |
| end | |
| function Convert:popObject01(img,debug) | |
| debugPrint(debug,".....Start of popObject01.....") | |
| local n,tag | |
| local t,out,header = {},{},{} | |
| -- read verification information | |
| n = 1 | |
| local nmax = self:colorToInt( color(img:get(self:xy(n))) ) | |
| t,n = self:imageToTable(n,img) | |
| tag = self:popTag(1,t,header) | |
| debugPrint(debug,"pop01 : header."..tag.." = "..tostring(header[tag])) | |
| t,n = self:imageToTable(n,img) | |
| tag = self:popTag(1,t,header) | |
| debugPrint(debug,"pop01 : header."..tag.." = "..tostring(header[tag])) | |
| if header.id~="JMV38-3d-object" | |
| then error("this image is not a 3d object saved to an image") | |
| elseif header.version ~= 1 | |
| then error("the object version ("..tostring(header.version) | |
| ..") is not compatible with this reader") | |
| end | |
| -- get other elements | |
| t,n = self:imageToTable(n,img) | |
| local tag,v,txt | |
| while t do | |
| tag = self:popTag(1,t,out) | |
| v = out[tag] | |
| if type(v)=="table" then | |
| txt = self:type(v).." = {"..tostring(v[1])..",...}" | |
| else | |
| txt = tostring(v) | |
| end | |
| debugPrint(debug,"pop01 : obj."..tag.." = "..txt) | |
| t,n = self:imageToTable(n,img) | |
| end | |
| return out | |
| end | |
| -- ********************************************** | |
| -- color table <=> image | |
| -- ********************************************** | |
| function Convert:xy(i) | |
| local x,y | |
| y = floor((i-1)/2048) | |
| x = i-1 - y*2048 | |
| return x+1,y+1 | |
| end | |
| function Convert:tableToImage(t) | |
| -- write table in an image | |
| local n = #t | |
| local h = floor(n/2048)+1 | |
| local w | |
| if n>2048 then w=2048 else w=n end | |
| local img = image(w,h) | |
| local x,y,i | |
| for i=1,n do | |
| x,y = self:xy(i) | |
| img:set(x,y,t[i]) | |
| -- if self:type(t[i])~="color" then | |
| -- error(i.." : "..tostring(t[i]).." : "..self:type(t[i])) end | |
| end | |
| return img | |
| end | |
| function Convert:imageToTable(n,img) | |
| -- read a table from an image: start at index n, where the number of colors | |
| -- to read is stored, read these colors, return the table and new index n value | |
| local w,h = img.width, img.height | |
| local x,y,i,c,k | |
| local t = {} | |
| local nmax = self:colorToInt( color(img:get(self:xy(n))) ) | |
| -- print("imageToTable : nmax = "..tostring(nmax)) | |
| if nmax==0 then t=nil | |
| else | |
| for i=0,nmax do | |
| c = color(img:get( self:xy(i+n) )) | |
| k = i+1 | |
| -- print("imageToTable : img["..(k).."] = "..tostring(c)) | |
| t[k] = c | |
| end | |
| end | |
| return t,(n+nmax+1) | |
| end | |
| -- ********************************************** | |
| -- object.tag <=> color table | |
| -- ********************************************** | |
| -- push an pop principles | |
| -- push(data,t) writes at the end of table t: | |
| -- the number of data words | |
| -- the data words themselves | |
| -- pop(n,t) | |
| -- reads n data words from table t | |
| -- converts these words to the data object 'out' | |
| -- returns 'out' and 'next_n' (for next pop start) | |
| -- ********************************************** | |
| function Convert:pushTag(tag,obj,out) | |
| local x = obj[tag] | |
| local typ = self:type(x) | |
| if self:supported(typ) then | |
| local n = #out -- record the position before the starting point of this data | |
| self:pushString(tag,out) -- write tag string | |
| self:pushString(typ,out) -- write tag type | |
| if typ=="string" then self:pushString(x,out) | |
| elseif typ=="number" then self:pushNumber(x,out) | |
| elseif typ=="image" then self:pushImage(x,out) | |
| elseif typ=="{color}" then self:pushColors(x,out) | |
| elseif typ=="{vec3}" then self:pushVec3(x,out) | |
| elseif typ=="{vec2}" then self:pushVec2(x,out) | |
| elseif typ=="{matrix}" then self:pushMatTable(x,out) | |
| elseif typ=="matrix" then self:pushMat(x,out) | |
| elseif typ=="mesh" then self:pushMesh(x,out) | |
| end | |
| local n1 = #out - n | |
| insert(out, n+1, self:intToColor(n1) ) | |
| else | |
| print("the type of '"..tag.."' is not supported for saving: "..typ) | |
| end | |
| end | |
| function Convert:popTag(n,t,obj) | |
| local input,nmax = self:getSubTable(n,t) | |
| local tag,typ,out | |
| local n1 = 1 | |
| tag,n1 = self:popString(n1,input) | |
| typ,n1 = self:popString(n1,input) | |
| if typ=="string" then out,n1 = self:popString(n1,input) | |
| elseif typ=="number" then out,n1 = self:popNumber(n1,input) | |
| elseif typ=="image" then out,n1 = self:popImage(n1,input) | |
| elseif typ=="{color}" then out,n1 = self:popColors(n1,input) | |
| elseif typ=="{vec3}" then out,n1 = self:popVec3(n1,input) | |
| elseif typ=="{vec2}" then out,n1 = self:popVec2(n1,input) | |
| elseif typ=="matrix" then out,n1 = self:popMat(n1,input) | |
| elseif typ=="{matrix}"then out,n1 = self:popMatTable(n1,input) | |
| elseif typ=="mesh" then out,n1 = self:popMesh(n1,input) | |
| end | |
| obj[tag]=out | |
| local next_n = n + nmax + 1 | |
| return tag, next_n | |
| end | |
| -- ********************************************** | |
| -- data structure <=> color table | |
| -- ********************************************** | |
| -- mesh | |
| function Convert:pushMesh(ms,t) | |
| local n = #t -- record the position before the starting point of this data | |
| local myTable = {} | |
| local texCoords,colors = {},{} | |
| myTable.vertices = ms.vertices | |
| myTable.texture = ms.texture | |
| if ms.texCoords then | |
| -- read texCoords to correct for mesh bug : y = 1-y | |
| for i=1,#ms.texCoords do texCoords[i] = ms:texCoord(i) end | |
| myTable.texCoords = texCoords | |
| end | |
| if ms.colors then | |
| -- read texCoords to correct for mesh bug : color = 0.0 to 1.0, instead of 0 to 255 | |
| for i=1,#ms.colors do colors[i] = ms:color(i) end | |
| myTable.colors = colors | |
| end | |
| if myTable.vertices then self:pushTag("vertices", myTable,t) end | |
| if myTable.texture then self:pushTag("texture", myTable,t) end | |
| if myTable.texCoords then self:pushTag("texCoords",myTable,t) end | |
| if myTable.colors then self:pushTag("colors", myTable,t) end | |
| local n1 = #t - n -- n1 is the number of data | |
| insert(t, n+1, self:intToColor(n1) ) | |
| end | |
| function Convert:popMesh(n,t) | |
| local input,nmax = self:getSubTable(n,t) | |
| local i,tag | |
| local ms = mesh() | |
| local n1 = 1 | |
| while n1<nmax do | |
| tag,n1 = self:popTag(n1,input,ms) | |
| end | |
| local next_n = n + nmax + 1 | |
| return ms, next_n | |
| end | |
| -- matrix | |
| function Convert:pushMat(m,t) | |
| local n = #t -- record the position before the starting point of this data | |
| local i | |
| for i=1,16 do | |
| insert(t,self:floatToColor(m[i])) | |
| end | |
| local n1 = #t - n -- n1 is the number of data | |
| insert(t, n+1, self:intToColor(n1) ) | |
| end | |
| function Convert:popMat(n,t) | |
| local input,nmax = self:getSubTable(n,t) | |
| local i | |
| local out = matrix() | |
| for i=1,16 do | |
| out[i] = self:colorToFloat( input[i] ) | |
| end | |
| local next_n = n + nmax + 1 | |
| return out, next_n | |
| end | |
| -- {matrix} | |
| function Convert:pushMatTable(matTable,t) | |
| local n = #t -- record the position before the starting point of this data | |
| local i | |
| local j,m | |
| for j=1,#matTable do | |
| m = matTable[j] | |
| for i=1,16 do | |
| insert(t,self:floatToColor(m[i])) | |
| end | |
| end | |
| local n1 = #t - n -- n1 is the number of data | |
| insert(t, n+1, self:intToColor(n1) ) | |
| end | |
| function Convert:popMatTable(n,t) | |
| local input,nmax = self:getSubTable(n,t) | |
| local i=1 | |
| local out = {} | |
| while i<nmax do | |
| local m = matrix() | |
| for j=1,16 do | |
| m[j] = self:colorToFloat( input[i+j-1] ) | |
| end | |
| out[(i+15)/16] = m | |
| i = i + 16 | |
| end | |
| local next_n = n + nmax + 1 | |
| return out, next_n | |
| end | |
| --{vec2} | |
| function Convert:pushVec2(verts,t) | |
| local n = #t -- record the position before the starting point of this data | |
| local i,v | |
| for i=1,#verts do | |
| v = verts[i] | |
| insert(t,self:floatToColor(v.x)) | |
| insert(t,self:floatToColor(v.y)) | |
| end | |
| local n1 = #t - n -- n1 is the number of data | |
| insert(t, n+1, self:intToColor(n1) ) | |
| end | |
| function Convert:popVec2(n,t) | |
| local input,nmax = self:getSubTable(n,t) | |
| local i=1 | |
| local out = {} | |
| while i<nmax do | |
| local v = vec2() | |
| v.x = self:colorToFloat( input[i] ) | |
| v.y = self:colorToFloat( input[i+1] ) | |
| out[(i+1)/2] = v | |
| i = i + 2 | |
| end | |
| local next_n = n + nmax + 1 | |
| return out, next_n | |
| end | |
| --{vec3} | |
| function Convert:pushVec3(vertices,t) | |
| local n = #t -- record the position before the starting point of this data | |
| local i,v | |
| for i=1,#vertices do | |
| v = vertices[i] | |
| insert(t,self:floatToColor(v.x)) | |
| insert(t,self:floatToColor(v.y)) | |
| insert(t,self:floatToColor(v.z)) | |
| end | |
| local n1 = #t - n -- n1 is the number of data | |
| insert(t, n+1, self:intToColor(n1) ) | |
| end | |
| function Convert:popVec3(n,t) | |
| local input,nmax = self:getSubTable(n,t) | |
| local i=1 | |
| local out = {} | |
| while i<nmax do | |
| local v = vec3() | |
| v.x = self:colorToFloat( input[i] ) | |
| v.y = self:colorToFloat( input[i+1] ) | |
| v.z = self:colorToFloat( input[i+2] ) | |
| out[(i+2)/3] = v | |
| i = i + 3 | |
| end | |
| local next_n = n + nmax + 1 | |
| return out, next_n | |
| end | |
| -- {color} | |
| function Convert:pushColors(colors,t) | |
| local n = #t -- record the position before the starting point of this data | |
| local i,v,r,g,b,a | |
| for i=1,#colors do | |
| v = colors[i] | |
| insert(t,v) | |
| end | |
| local n1 = #t - n -- n1 is the number of data | |
| insert(t, n+1, self:intToColor(n1) ) | |
| end | |
| function Convert:popColors(n,t) | |
| local input,nmax = self:getSubTable(n,t) | |
| local i | |
| local out = {} | |
| for i=1,nmax do out[i] = input[i] end | |
| local next_n = n + nmax + 1 | |
| return out, next_n | |
| end | |
| -- image | |
| function Convert:pushImage(img,t) | |
| local n = #t -- record the position before the starting point of this data | |
| local w,h,x,y | |
| w,h = img.width, img.height | |
| insert(t,self:intToColor(w)) | |
| insert(t,self:intToColor(h)) | |
| for x=1,w do | |
| for y=1,h do | |
| insert(t,color(img:get(x,y))) | |
| end | |
| end | |
| local n1 = #t - n -- n1 is the number of data | |
| insert(t, n+1, self:intToColor(n1) ) | |
| end | |
| function Convert:popImage(n,t) | |
| local input,nmax = self:getSubTable(n,t) | |
| local w,h,x,y | |
| w = self:colorToInt(input[1]) --n+1 | |
| h = self:colorToInt(input[2]) | |
| local out = image(w,h) | |
| local i = 3 -- n+3 | |
| for x=1,w do | |
| for y=1,h do | |
| out:set(x,y,input[i]) | |
| i = i + 1 | |
| end | |
| end | |
| local next_n = n + nmax + 1 | |
| return out, next_n | |
| end | |
| -- number | |
| function Convert:pushNumber(x,t) | |
| local n = #t -- record the position before the starting point of this data | |
| insert(t,self:floatToColor(x)) | |
| local n1 = #t - n -- n1 is the number of data | |
| insert(t, n+1, self:intToColor(n1) ) | |
| end | |
| function Convert:popNumber(n,t) | |
| local input,nmax = self:getSubTable(n,t) | |
| local out = self:colorToFloat( input[1] ) | |
| local next_n = n + nmax + 1 | |
| return out, next_n | |
| end | |
| -- string | |
| function Convert:pushString(txt,t,subCall) | |
| local n = #t -- record the position before the starting point of this data | |
| local t1,t2 | |
| if txt:len()>4 then | |
| t1 = txt:sub(1,4) | |
| t2 = txt:sub(5) | |
| else | |
| t1 = txt | |
| end | |
| insert(t,self:stringToColor(t1)) | |
| if t2 then self:pushString(t2,t,true) end | |
| if not subCall then | |
| local n1 = #t - n -- n1 is the number of data | |
| insert(t, n+1, self:intToColor(n1) ) | |
| end | |
| end | |
| function Convert:popString(n,t) | |
| local input,nmax = self:getSubTable(n,t) | |
| local out = {} | |
| local i | |
| for i=1,nmax do out[i] = self:colorToString(input[i]) end | |
| out = table.concat(out,"") | |
| local next_n = n + nmax + 1 | |
| return out, next_n | |
| end | |
| -- get table part | |
| function Convert:getSubTable(n,t) | |
| local out = {} | |
| local nmax = self:colorToInt( t[n] ) | |
| for i=1,nmax do out[i] = t[i+n] end | |
| return out,nmax | |
| end | |
| -- ********************************************** | |
| -- basic function to convert to and from colors | |
| -- ********************************************** | |
| local abs = math.abs | |
| local log10 = math.log10 | |
| local pow = math.pow | |
| -- type(v):"nil", "number", "string", "boolean", "table", "function", "thread", "userdata". | |
| function Convert:type(x) | |
| local txt = type(x) | |
| function typeCompare(x,ref) | |
| -- nb: returns an error if x or ref have no metatable! | |
| local i = getmetatable(x).__index | |
| local j = getmetatable(ref).__index | |
| return (i==j) | |
| end | |
| if txt == "userdata" then | |
| if typeCompare(x,vec2()) then txt ="vec2" | |
| elseif typeCompare(x,vec3()) then txt ="vec3" | |
| elseif typeCompare(x,color()) then txt ="color" | |
| elseif typeCompare(x,image(1,1)) then txt ="image" | |
| elseif typeCompare(x,matrix()) then txt ="matrix" | |
| elseif typeCompare(x,mesh()) then txt ="mesh" | |
| end | |
| end | |
| if txt == "table" then | |
| txt = "{"..self:type(x[1]).."}" | |
| end | |
| return txt | |
| end | |
| function Convert:intToColor(dat) | |
| -- abs value coded on 4 octets uint (r,g,b,a) | |
| local r,g,b,a = 0,0,0,0 | |
| local x | |
| -- chech no sign | |
| x = abs(dat) | |
| if x~=dat then error("only uint supported : "..dat) end | |
| -- convert in octet basis | |
| r = x % 256 | |
| x = floor(x/256) | |
| g = x % 256 | |
| x = floor(x/256) | |
| b = x % 256 | |
| x = floor(x/256) | |
| a = x | |
| if a>255 then error("this integer is too big to save : "..dat) end | |
| return color(r,g,b,a) | |
| end | |
| function Convert:colorToInt(c) | |
| local r,g,b,a = c.r, c.g, c.b, c.a | |
| local i = r +256*(g + 256*(b +256*a)) | |
| return i | |
| end | |
| function Convert:floatToColor(dat) | |
| -- abs value coded on 3 octets (r,g,b) | |
| -- a is coding the power of 10, from -64 to +63 | |
| -- the sign is coded by 1 bit (+128) in a | |
| -- accuracy limit: about less than 10/(256*256*256) relative error | |
| local r,g,b,a = 0,0,0,0 | |
| local x,sgn,p,c | |
| -- remove the sign and save it | |
| x = abs(dat) | |
| if x==dat then sgn = 0 else sgn = 128 end | |
| -- get the exponent | |
| if x==0 then p=0 else | |
| p = log10(x) | |
| p = floor(p) | |
| end | |
| if (p<-64) or (63<p) then -- overflow | |
| -- in case of overflow clip the data | |
| if p<-64 then p=-64 else p=63 end | |
| r,g,b,a =255,255,255,127 | |
| else | |
| -- convert to int | |
| x = x / pow(10,p)/10 -- number x is now : 0.abcdefg with a from 1 to 9 | |
| x = floor( x *255 * 256 * 256 ) | |
| -- convert to octet basis | |
| c = self:intToColor(x) | |
| r,g,b,a = c.r, c.g, c.b, c.a | |
| if a>0 then error("bug: a should be 0") end | |
| end | |
| -- a saves sign and exponent | |
| a = (p + 64) + sgn | |
| return color(r,g,b,a) | |
| end | |
| function Convert:colorToFloat(c) | |
| local r,g,b,a = c.r, c.g, c.b, c.a | |
| local sgn | |
| if a >127 then sgn =-1 ; a=a-128 else sgn =1 end | |
| local p = a - 64 | |
| local x = ((r/256 + g)/256 +b)/255 * pow(10,p) * 10 * sgn | |
| return x | |
| end | |
| function Convert:stringToColor(t) | |
| local r,g,b,a = 0,0,0,0 | |
| local l = t:len() | |
| if l>0 then r = t:byte(1) end | |
| if l>1 then g = t:byte(2) end | |
| if l>2 then b = t:byte(3) end | |
| if l>3 then a = t:byte(4) end | |
| if l>4 then error("the text: "..t.." is too long (4 chars max).") end | |
| return color(r,g,b,a) | |
| end | |
| function Convert:colorToString(c) | |
| local r,g,b,a = c.r, c.g, c.b, c.a | |
| local txt = "" | |
| if a>0 then txt = string.char(r,g,b,a) | |
| elseif b>0 then txt = string.char(r,g,b) | |
| elseif g>0 then txt = string.char(r,g) | |
| elseif r>0 then txt = string.char(r) | |
| end | |
| return txt | |
| 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
| -- 0 conversion | |
| -- unit test of variuos fonctions | |
| function setup() | |
| convert = Convert() | |
| -- types | |
| typeUnitTests() | |
| -- integer | |
| intUnitTests() | |
| -- float | |
| floatUnitTests() | |
| -- string | |
| stringUnitTests() | |
| -- tables | |
| myobj = ObjectClassForTest() | |
| testPushString0() | |
| testPushTag("name",myobj) | |
| testPushTag("version",myobj) | |
| img1 = testPushTag("texture",myobj.ms) | |
| listTypes(myobj) | |
| print("vertices : "..convert:type(myobj.ms.vertices)) | |
| print("texCoords : "..convert:type(myobj.ms.texCoords)) | |
| print("colors : "..convert:type(myobj.ms.colors)) | |
| testPushColors("colors",myobj.ms) | |
| testPushVec3("vertices",myobj.ms) | |
| testPushVec2("texCoords",myobj.ms) | |
| testPushMatrixTable("mt",myobj) | |
| testPushMatrix("m",myobj) | |
| testPushMesh("ms",myobj) | |
| testPushObject(myobj) | |
| testSaveLoadImage(myobj) | |
| testSaveLoad(myobj) | |
| -- sprite() | |
| end | |
| function testSaveLoad(obj) | |
| local debug = true | |
| print(" ------------- ") | |
| print(" ----- push -------- ") | |
| convert:save(obj,"titi",debug) | |
| print(" ----- pop -------- ") | |
| local obj2 = {} | |
| convert:load(obj2,"titi",debug) | |
| end | |
| function testSaveLoadImage(obj) | |
| print(" ------------- ") | |
| print("Have the images been generated?") | |
| convert:saveImage("titi",obj.ms.texture) | |
| img2 = readImage("Documents:titi") | |
| print(img2) | |
| img3 = convert:readImage("titi") | |
| print(img3) | |
| end | |
| function testPushObject(obj) | |
| print(" ------------- ") | |
| print(" push and pop object") | |
| local debug=true | |
| local img = convert:pushObject01(obj,debug) | |
| print("result image:"..tostring(img)) | |
| local obj2 = convert:popObject01(img,debug) | |
| end | |
| function listTypes(a) | |
| print(" ------------- ") | |
| for t,v in pairs(a) do | |
| print(t.." : "..convert:type(v)) | |
| end | |
| end | |
| function typeUnitTests() | |
| local t | |
| print(" ------------- ") | |
| print("Type unit tests") | |
| t = 5 | |
| print("this data: \n",tostring(t),"\n is a : "..convert:type(t)) | |
| t = vec2(1,2) | |
| print("this data: \n",tostring(t),"\n is a : "..convert:type(t)) | |
| t = vec3(1,2,3) | |
| print("this data: \n",tostring(t),"\n is a : "..convert:type(t)) | |
| t = color(146, 45, 45, 255) | |
| print("this data: \n",tostring(t),"\n is a : "..convert:type(t)) | |
| t = matrix() | |
| print("this data: \n",tostring(t),"\n is a : "..convert:type(t)) | |
| t = image(10,10) | |
| print("this data: \n",tostring(t),"\n is a : "..convert:type(t)) | |
| t = mesh() | |
| print("this data: \n",tostring(t),"\n is a : "..convert:type(t)) | |
| end | |
| local clock = os.clock | |
| local floor = math.floor | |
| function testPushMesh(tag,obj) | |
| print(" ------------- ") | |
| print("object.mesh to color table, and back") | |
| local t,p = {},{} | |
| print(tostring(obj[tag])) | |
| local i,v,ob | |
| ob = obj[tag] | |
| i="vertices" ; print(i.." : "..tostring(ob[i])) | |
| i="texCoords" ; print(i.." : "..tostring(ob[i])) | |
| i="texture" ; print(i.." : "..tostring(ob[i])) | |
| i="colors" ; print(i.." : "..tostring(ob[i])) | |
| local t0 = clock() | |
| convert:pushTag(tag,obj,t) | |
| local t1 = clock() | |
| print("tag => table "..floor((t1-t0)*1000).." ms") | |
| print("intermediate table has "..#t.." elements") | |
| local t2 = clock() | |
| convert:popTag(1,t,p) | |
| local t3 = clock() | |
| print("table => tag "..floor((t3-t2)*1000).." ms") | |
| print(tostring(p[tag])) | |
| ob = p[tag] | |
| i="vertices" ; print(i.." : "..tostring(ob[i])) | |
| i="texCoords" ; print(i.." : "..tostring(ob[i])) | |
| i="texture" ; print(i.." : "..tostring(ob[i])) | |
| i="colors" ; print(i.." : "..tostring(ob[i])) | |
| end | |
| function testPushMatrix(tag,obj) | |
| print(" ------------- ") | |
| print("object.matrix to color table, and back") | |
| local t,p = {},{} | |
| print(tostring(obj[tag])) | |
| local i,v,ob | |
| convert:pushTag(tag,obj,t) | |
| print("intermediate table has "..#t.." elements") | |
| convert:popTag(1,t,p) | |
| print(tostring(p[tag])) | |
| end | |
| function testPushMatrixTable(tag,obj) | |
| print(" ------------- ") | |
| print("object.{matrix} to color table, and back") | |
| local t,p = {},{} | |
| print(obj[tag]) | |
| print("initial table has "..#obj[tag].." elements") | |
| local i,v,ob | |
| ob = obj[tag] | |
| for i,v in ipairs(ob) do print(tostring(ob[i])) end | |
| convert:pushTag(tag,obj,t) | |
| print("intermediate table has "..#t.." elements") | |
| convert:popTag(1,t,p) | |
| print("final table has "..#p[tag].." elements") | |
| ob = p[tag] | |
| for i,v in ipairs(ob) do print(tostring(ob[i])) end | |
| end | |
| function testPushVec2(tag,obj) | |
| print(" ------------- ") | |
| print("object.{Vec2} to color table, and back") | |
| local t,p = {},{} | |
| print(obj[tag]) | |
| print("initial table has "..#obj[tag].." elements") | |
| local i,v,ob | |
| ob = obj[tag] | |
| for i,v in ipairs(ob) do print(tostring(ob[i])) end | |
| convert:pushTag(tag,obj,t) | |
| print("intermediate table has "..#t.." elements") | |
| convert:popTag(1,t,p) | |
| print("final table has "..#p[tag].." elements") | |
| ob = p[tag] | |
| for i,v in ipairs(ob) do print(tostring(ob[i])) end | |
| end | |
| function testPushVec3(tag,obj) | |
| print(" ------------- ") | |
| print("object.{Vec3} to color table, and back") | |
| local t,p = {},{} | |
| print(obj[tag]) | |
| print("initial table has "..#obj[tag].." elements") | |
| local i,v,ob | |
| ob = obj[tag] | |
| for i,v in ipairs(ob) do print(tostring(ob[i])) end | |
| convert:pushTag(tag,obj,t) | |
| print("intermediate table has "..#t.." elements") | |
| convert:popTag(1,t,p) | |
| print("final table has "..#p[tag].." elements") | |
| ob = p[tag] | |
| for i,v in ipairs(ob) do print(tostring(ob[i])) end | |
| end | |
| function testPushColors(tag,obj) | |
| print(" ------------- ") | |
| print("object.{color} to color table, and back") | |
| local t,p = {},{} | |
| print(obj[tag]) | |
| print("initial table has "..#obj[tag].." elements") | |
| local i,v,ob | |
| ob = obj[tag] | |
| for i,v in ipairs(ob) do print(tostring(ob[i])) end | |
| convert:pushTag(tag,obj,t) | |
| print("intermediate table has "..#t.." elements") | |
| convert:popTag(1,t,p) | |
| print("final table has "..#p[tag].." elements") | |
| ob = p[tag] | |
| for i,v in ipairs(ob) do print(tostring(ob[i])) end | |
| end | |
| function testPushTag(tag,obj) | |
| local t = {} | |
| print(" ------------- ") | |
| print("tag <=> table") | |
| print(tag.." : "..tostring(obj[tag])) | |
| local t0 = clock() | |
| convert:pushTag(tag,obj,t) | |
| local t1 = clock() | |
| print("tag => table "..floor((t1-t0)*1000).." ms") | |
| local p = {} | |
| local t2 = clock() | |
| local tag = convert:popTag(1,t,p) | |
| local t3 = clock() | |
| print("table => tag "..floor((t3-t2)*1000).." ms") | |
| print(tag.." : "..tostring(p[tag])) | |
| return p[tag] | |
| end | |
| function testPushString0() | |
| print(" ------------- ") | |
| local str1 ="tag=name" | |
| local str2 ="type=string" | |
| local str3 ="hello world" | |
| print(str1) | |
| print(str2) | |
| print(str3) | |
| local n,t = 1,{} | |
| convert:pushString(str1,t) | |
| convert:pushString(str2,t) | |
| convert:pushString(str3,t) | |
| print("intermediate table has "..#t.." elements") | |
| local str | |
| str,n = convert:popString(n,t) print(str) | |
| str,n = convert:popString(n,t) print(str) | |
| str,n = convert:popString(n,t) print(str) | |
| end | |
| function stringUnitTests() | |
| print(" ------------- ") | |
| print("string unit test") | |
| testString() | |
| testString("") | |
| testString("h") | |
| testString("he") | |
| testString("hel") | |
| testString("hell") | |
| testString("=") | |
| testError(testString,"[{()}]") | |
| end | |
| function testError(f,arg) | |
| local status,err = pcall(f,arg) | |
| if status==false | |
| then print("ok : "..tostring(arg).." has generated an error : "..err) | |
| else print("FALSE : this should generate an error : "..tostring(arg)) | |
| end | |
| end | |
| function testString(i) | |
| local c,t,txt | |
| if i then | |
| c=convert:stringToColor(i) | |
| t=convert:colorToString(c) | |
| if (i==t) then txt="ok" else txt="FALSE" end | |
| print(txt.." : '"..i.."'".." = "..tostring(c).." = ".."'"..t.."'") | |
| else | |
| print("") | |
| print("string to color and back to string") | |
| end | |
| end | |
| function intUnitTests() | |
| print(" ------------- ") | |
| print("test of conversion functions") | |
| print("") | |
| print("intToColor") | |
| testUInt(1) | |
| testUInt(1000) | |
| testUInt(1000000) | |
| testUInt(100000000) | |
| testError(testUInt,-1) | |
| testError(testUInt,256*256*256*256+10) | |
| end | |
| function testUInt(i) | |
| local c,i1,txt | |
| c=convert:intToColor(i) | |
| i1=convert:colorToInt(c) | |
| if (i==i1) then txt="ok" else txt="FALSE" end | |
| print(txt.." : "..i.." = "..tostring(c).." = "..i1) | |
| end | |
| function floatUnitTests() | |
| print(" ------------- ") | |
| print("Float unit tests") | |
| test2() | |
| test2(0) | |
| test2(2) | |
| test2(1003) | |
| test2(1000003) | |
| test2(-19) | |
| test2(-8000) | |
| test2(-1000003) | |
| test2(0.2) | |
| test2(0.00003) | |
| test2(0.00000000003) | |
| test2(-0.5) | |
| test2(-0.00003) | |
| test2(-0.000008888888) | |
| test2(math.random()) | |
| test2(math.pi) | |
| test2(math.pi*math.pow(10,22)) | |
| test2(-math.pi*math.pow(10,22)) | |
| end | |
| function test2(i) | |
| local precision = 10/256/256/255 | |
| if i then | |
| local c,i1,t,txt | |
| c=convert:floatToColor(i) | |
| i1=convert:colorToFloat(c) | |
| local err = (i-i1)/i | |
| if math.abs(err)<precision then txt="ok" else txt="FALSE" end | |
| print(txt.." : "..i.." = "..tostring(c).." = "..i1) | |
| else | |
| print("") | |
| print("floatToColor and back to float") | |
| print("precision required : "..precision) | |
| end | |
| end | |
| -- This function gets called once every frame | |
| function draw() | |
| -- This sets a dark background color | |
| background(40, 40, 50) | |
| -- This sets the line thickness | |
| strokeWidth(5) | |
| -- Do your drawing here | |
| sprite( myobj.ms.texture,WIDTH/4,HEIGHT/2) | |
| sprite(img1,WIDTH/2,HEIGHT/2) | |
| sprite(img2,WIDTH/2,HEIGHT/4*3) | |
| sprite(img3,WIDTH/4,HEIGHT/4*3) | |
| 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
| ObjectClassForTest = class() | |
| function ObjectClassForTest:init(x) | |
| self.name ="object_name" -- a string | |
| self.version = 1 -- version of couple: object + save method | |
| self.m = matrix() -- position of the object copies | |
| self.mt = {matrix(),matrix():translate(100,0,0)} -- position of the object copies | |
| self.sv = { {1},{2},{3} } -- summit vectors: for each summit a table of vertice indexes | |
| self.sf = { {1},{1},{1} } -- summit faces: for each summit a table of face indexes | |
| self.fs = { {1,2,3} } -- face summits: each face has 3 summit index in a table | |
| -- nota: if 1,2,3 is a face, 12:cross(13) is oriented to the outside of the object | |
| local z = vec3(0,0,1) | |
| -- normals: at least one of those is needed to draw shadows: | |
| self.sn = { z, z, z} -- summit normals: for each summit a vec3 (optionnal) | |
| self.fn = {z} -- face normals: for each face a vec3 (optionnal) | |
| self.vn = { z, z, z} -- vertices normals: for each vertice a vec3 (optionnal) | |
| self.ms = mesh() -- mesh | |
| -- vertices: a table of vec3, by group of 3, corresponding to faces index*3+0,1,2 | |
| self.ms.vertices = {vec3(-50,-50,0),vec3(50,-50,0),vec3(-50,50,0)} | |
| -- texture coords: a table of vec2, by group of 3, corresponding to faces index*3+0,1,2 | |
| -- self.ms.texCoords = {vec2(0,0),vec2(1,0),vec2(0,1)} | |
| self.ms.texCoords = {vec2(3/32,3/32),vec2(29/32,3/32),vec2(3/32,29/32)} | |
| local img = readImage("Documents:mechanics") | |
| --setContext(img) background(255, 255, 255, 255) setContext() | |
| self.ms.texture = img | |
| -- colors: a table of colors, by group of 3, corresponding to faces index*3+0,1,2 | |
| -- self.ms.colors = {color(255, 0, 0, 255),color(0, 255, 2, 255),color(0, 19, 255, 255)} | |
| local white = color(255, 255,255, 255) | |
| self.ms.colors = {white,white,white} | |
| self.img = img -- an image for various usages | |
| self.icon = image(101,101) -- an image used to save a small view of the object | |
| self.visible = true | |
| -- functions to convert object <=> image | |
| self.converter = Convert() | |
| end | |
| function ObjectClassForTest:draw() | |
| -- Codea does not automatically call this method | |
| end | |
| function ObjectClassForTest:touched(touch) | |
| -- Codea does not automatically call this method | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment