Skip to content

Instantly share code, notes, and snippets.

@AntonioCiolino
Created November 19, 2012 23:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AntonioCiolino/4114671 to your computer and use it in GitHub Desktop.
Save AntonioCiolino/4114671 to your computer and use it in GitHub Desktop.
Saves a Codea mesh item as a PLY object
ply
format ascii 1.0
comment Written by WritePLY - a Codea LUA project by Antonio Ciolino
element vertex 36
property float x
property float y
property float z
property uchar red
property uchar green
property uchar blue
property uchar alpha
element face 12
property list uchar int vertex_index
end_header
-1 -1 1 237 83 100 255
1 -1 1 150 73 100 255
1 1 1 226 138 100 255
-1 -1 1 214 94 100 255
1 1 1 154 66 100 255
-1 1 1 245 133 100 255
1 -1 1 186 105 100 255
1 -1 -1 172 61 100 255
1 1 -1 249 126 100 255
1 -1 1 162 116 100 255
1 1 -1 199 60 100 255
1 1 1 238 116 100 255
1 -1 -1 150 125 100 255
-1 -1 -1 226 61 100 255
-1 1 -1 215 106 100 255
1 -1 -1 153 133 100 255
-1 1 -1 244 66 100 255
1 1 -1 187 94 100 255
-1 -1 -1 171 138 100 255
-1 -1 1 249 73 100 255
-1 1 1 163 84 100 255
-1 -1 -1 198 139 100 255
-1 1 1 238 82 100 255
-1 1 -1 150 74 100 255
-1 1 1 225 138 100 255
1 1 1 216 93 100 255
1 1 -1 153 66 100 255
-1 1 1 244 134 100 255
1 1 -1 188 104 100 255
-1 1 -1 170 61 100 255
-1 -1 -1 249 126 100 255
1 -1 -1 163 115 100 255
1 -1 1 197 60 100 255
-1 -1 -1 239 117 100 255
1 -1 1 150 125 100 255
-1 -1 1 224 61 100 255
3 0 1 2
3 3 4 5
3 6 7 8
3 9 10 11
3 12 13 14
3 15 16 17
3 18 19 20
3 21 22 23
3 24 25 26
3 27 28 29
3 30 31 32
3 33 34 35
w = WritePLY("Saving a mesh")
result = w:Save(yourmesh)
--
-- ReadPLY.lua
-- This file will need some work to operate standalone;
-- it is part of the HTTPLoader library, but extracted here for JVM38's use.
--
ReadPLY = class()
--
function ReadPLY:init()
self.renderitems={} -- assigned later...
-- self.plyFileName=file
self.ParsedFile = nil
self.texcoords = {}
end
function ReadPLY:draw()
-- draw all of the renderitems in this mesh()
if (self.renderitems~=nil) then
for k,v in pairs(self.renderitems) do
v:draw()
end
end
end
--For hack's sake, pass the PLY file string here. obj is the PLY string for this example.
function ReadPLY:ProcessObject(obj)
self.ParsedFile=obj
self:ProcessScene(self)
--log("string parsing done.")
end
function ReadPLY:ProcessScene()
self:ProcessSceneHeader()
self:ProcessSceneBody()
end
function ReadPLY:ProcessSceneHeader()
elements={} -- elements of this file
endheader = string.find(self.ParsedFile, "end_header")
header = string.sub(self.ParsedFile, 1, endheader-1)
body = string.sub(self.ParsedFile, endheader+11, 999999)
-- make a table to interpret the header. this is the guide to read the file.
for token in string.gmatch(header, "[^\r\n]+") do
-- pack each string and process
-- special case find the texture file if it exists
i= string.find(token, "comment TextureFile")
if (i~=nil) then
texture=string.sub(token, string.find(token, "comment TextureFile")+20, 99)
--AC: Commented out need HTTPLoader for this.
--if (string.find(texture,"http://")~=nil) then
-- self.d:Add(texture, DEFERRED_TEXTURE, ignoreCache)
--else
--self.d:Add("Documents:"..texture, DEFERRED_TEXTURE,ignoreCache)
-- self.d:Add(self.d.rootPath..texture, DEFERRED_TEXTURE,ignoreCache)
--end
--log("Deferred loading "..self.d.files[1].file) --texture)
end
i=string.find(token,"element")
if (i~=nil) then
--we have a new element
tbl = split(token, " ")
entry= { name=tbl[2], value=tbl[3], properties={}, lines={} }
table.insert(elements, entry)
end
i=string.find(token, "property")
if (i~=nil) then
tbl = split(token, " ")
indexed = 0
if tbl[2] == "list" then
-- this data is a lookup list. unused, we are hardcoding our lookups
--against texcoords and faces.
-- later we should deal with uchar, list data
indexed = 1
end
prop = { property=tbl[table.maxn(tbl)], index=indexed}
table.insert(entry.properties, prop)
end
end
end
function ReadPLY:ProcessSceneBody()
self.newItem=mesh()
local pcolor={} --color array, if defined, per vertex. not the packed color obj
local tx = {} --texture coordindates, if ddefined
local vertices={} --data that gets sent to mesh triangles of point data
local points = {} --stores points, eventaully used to build vertices
local colors={}
local texcoord={}
-- read through the body string using the header as a guide
-- all elements have a value
--lines=split(body, "[^\r\n]") failed!
lines=GetTable(body, "[^\r\n]+")
offset=0
for k,v in pairs(elements) do
tmp = {} --clar my temp table
-- get value number of lines and process
for i=1, v.value do
table.insert(tmp, lines[i+offset])
end
offset=v.value
v.lines = tmp
--process verts these are points?
if v.name=="vertex" then
for lk, lv in pairs(v.lines) do
pt = vec3(0,0,0)
items=GetTable(lv, "[^%s]+") --"([-+]?[0-9]*\.?[0-9]+)")
--for k,v in pairs(items) do --needss to be aa case stmt later
pt.x=items[1]+0
pt.y=items[2]+0
pt.z=items[3]+0
if(#items>3) then --hack!!
--colors of the verts go here
r = items[4]+0
g = items[5]+0
b = items[6]+0
-- a = items[7]+0
end
--end
table.insert(points, pt)
if (#items >3) then
table.insert(pcolor, color(r,g,b,255))
end
pt = vec3(0,0,0)
end
end
if v.name=="face" then
--takes us from points to triangles...we pack these into the mesh!
for lk, lv in pairs(v.lines) do
items=GetTable(lv, "[^%s]+")
fv={}
out={}
vtx =vec3(0,0,0)
--todo: read the structure data...
--vertex_indices portion. 3 0 1 2
vtx = items[2]+1
table.insert(vertices, points[vtx])
table.insert(colors, pcolor[vtx])
vtx = items[3]+1
table.insert(vertices, points[vtx])
table.insert(colors, pcolor[vtx])
vtx = items[4]+1
table.insert(vertices, points[vtx])
table.insert(colors, pcolor[vtx])
--if we have teturecoords, read then here.
if (#items > 4) then
uv=vec2(items[6], items[7])
table.insert(texcoord, uv)
uv=vec2(items[8], items[9])
table.insert(texcoord, uv)
uv=vec2(items[10], items[11])
table.insert(texcoord, uv)
end
end
end
end
--log ("final points "..#points)
--log ("final verts "..#vertices)
--log ("final colors "..#colors)
--log ("final texcoord "..#texcoord)
self.newItem.vertices=vertices -- a vec3 of points
if (#colors>1) then self.newItem.colors=colors end
if (#texcoord> 1) then
self.newItem.texCoords=texcoord
self.newItem:setColors(255,255,255,255) --IF WE HAVE A TEXTURE, IGNORE COLOR FOR NOW
end
--put new shape in a table for later rendering
--table.insert(self.renderitems, self.newItem)
return self.newItem -- <==-- this is the mesh
-- if we have urls to load, do so...
--if (#self.d.files>0) then
-- log("Loading texture...")
-- self.d:LoadAll(self.newItem)
--end
end
--
-- WritePLY.lua
--
WritePLY = class()
function WritePLY:init(comment)
-- load a mesh object and write it as a simple PLY. we are not going to do
-- textures.
--if a comment is wanted, add it during object creation or edit it while instance exists.
self.comment = comment
end
function WritePLY:Save(obj)
startheader = "ply\r\nformat ascii 1.0\r\n"
comments = "comment Written by WritePLY - a Codea LUA project by Antonio Ciolino "
if (self.comment ~=nil) then
comments = comments .. self.comment
end
comments = comments .. "\r\n"
meta1 = "element vertex "
meta2 = "property float x\r\nproperty float y\r\nproperty float z\r\n"
meta2 = meta2 .. "property uchar red\r\nproperty uchar green\r\n"
meta2 = meta2 .. "property uchar blue\r\nproperty uchar alpha\r\n"
meta3 = "element face "
meta4 = "property list uchar int vertex_index\r\n"
endheader = "end_header\r\n"
--modify meta1 and meta3
pointlist = {}
colorlist = {}
verts = ""
faces = ""
colors = obj.colors
for x=1, #obj.vertices do --these are locations in space. 3 of them make a face
v = obj:vertex(x)
pt = v.x .. " " .. v.y .. " " ..v.z --a triplet of points
c = colors[x]
clr = math.floor(c.r*255) .. " " ..
math.floor(c.g*255) .. " " ..
math.floor(c.b*255) .. " " ..
math.floor(c.a*255)
table.insert(pointlist, pt) --add to a table to index later. THIS IS A FACE.
table.insert(colorlist, clr) --store the color of the vertex.
end
meta1 = meta1 .. #obj.vertices .. "\r\n"
for x=1, #pointlist,3 do
verts = verts .. tostring(pointlist[x]) .. " " .. tostring(colorlist[x]) .. " \r\n" ..
tostring(pointlist[x+1]) .. " " .. tostring(colorlist[x+1]) .. "\r\n" ..
tostring(pointlist[x+2]) .. " " .. tostring(colorlist[x+2]) .. "\r\n"
--ply files are zero based for indices
idx = x-1
faces = faces .. "3 " .. tostring(idx) .. " " ..
tostring(idx+1) .. " " ..
tostring(idx+2) .. "\r\n"
end
meta3 = meta3 .. #pointlist / 3 .. "\r\n"
header = startheader ..comments .. meta1 ..meta2 .. meta3 .. meta4 .. endheader
output = header .. verts .. faces
return output
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment