function klogo_meshload(packed_data)
  local data= unpod(packed_data)
  local mesh= {}
  local pos= 0

  local function get16(cnt)
    cnt= cnt or 1
    local tmp= pos
    pos+=cnt
    return data:get(tmp, cnt)
  end

  local function getfloat()
    local int,frac= get16(),get16()
    return ((int<<16)+(frac&0xffff))/65536.0
  end

  local function getvec3list()
    local num= get16()    
    local values= userdata("f64", 3, num)
    for i=0,num-1 do
      local x,y,z= getfloat(),getfloat(),getfloat()
      values:set(0,i, x,y,z)
    end
    return values
  end

  local function getvec2list()
    local num= get16()
    local values= userdata("f64", 3, num)
    for i=0,num-1 do
      local x,y= getfloat(),getfloat()
      values:set(0,i, x,256-y,0)
    end
    return values
  end

  local function getnormallist(scale)
    local num= get16()
    local values= userdata("f64", 3, num)
    scale= scale or 1.0
    scale/=32767
    for i=0,num-1 do
      local x,y,z= get16(3)
      values:set(0,i, x*scale, y*scale, z*scale)
    end
    return values
  end

  local function getindexlist(cnt)
    local num= get16()
    local values= userdata("i32", cnt, num)
    for i=0,num-1 do
      values:set(0,i,  get16(cnt))
    end
    return values
  end
  
--  store("test-lz4.pod", pod(mesh, 3))

  mesh.pos= getvec3list()
  mesh.uv=  getvec2list()
  mesh.nrm= getnormallist(128)

  local num_groups= get16()
  local mat_id= get16()
  local temp_quads= getindexlist(4)
  local temp_tris= getindexlist(3)

  local numquads,numtris= 0,0
  if (temp_quads~=nil) numquads= temp_quads:height()
  if (temp_tris~= nil) numtris=  temp_tris:height()


  mesh.quad_indices= userdata("i32", 4, numquads + numtris)
  for i=0,numquads-1 do
    local i1,i2,i3,i4= temp_quads:get(0,i, 4)
    mesh.quad_indices:set(0,i, i1,i2,i3,i4)
  end
  -- convert tris to quads (TODO!)
  for i=0,numtris-1 do
    local i1,i2,i3= temp_tris:get(0,i, 3)
    mesh.quad_indices:set(0,numquads+i, i1,i2,i3,i3)
  end
  numquads+=numtris

  local nv= mesh.pos:height()
  mesh.screen_pos= userdata("f64", 3, nv)
  mesh.screen_nrm= userdata("f64", 3, nv)
  mesh.proj_verts= userdata("f64", 8, nv)

  mesh.facenormals= userdata("f64", 3, numquads+1)
  mesh.screen_facenormals= userdata("f64", 3, numquads+1)
  mesh.numpolys= numquads

  -- calculate face normals
  mesh.cull_idx= userdata("i32", numquads, 1)
  for face=0, numquads-1 do
    local idx= mesh.quad_indices:row(face)
    local i1= idx[0]
    local i2= idx[1]
    local i3= idx[2]
    local i4= idx[3]

    -- one vertex of face for backface-culling test
    -- these vertices have different size (only x,y,z) than quad_indices below which point to complete vertices (x,y,z, u,v, etc)
    mesh.cull_idx:set(face,0, i1*3)

    local n

    if (i3!=i4) then
      -- quad

      local v1= mesh.pos:row(i1)
      local v2= mesh.pos:row(i2)
      local v3= mesh.pos:row(i3)
      local v4= mesh.pos:row(i4)

      -- cross product gives normal
      n= (v1-v3):cross(v2-v4)
    else
      -- triangle, duplicate last vertex
      local v1= mesh.pos:row(i1)
      local v2= mesh.pos:row(i2)
      local v3= mesh.pos:row(i3)

      n= (v1-v3):cross(v2-v3)
    end

    n:div(n:magnitude(), true)

    -- normalize normal
    mesh.facenormals:set( 0, face, n.x, n.y, n.z )

    -- scale index with vertex size
    mesh.quad_indices:set(0, face, i1*8,i2*8,i3*8,i4*8)
  end

  mesh.facenormals:set( 0, numquads, 0, 0, 0 )  -- 

  -- scale UVs
  for i=0,mesh.uv:height()-1 do
    local u,v= mesh.uv:get(0,i,2)
    mesh.uv:set(0,i, u*256.0, (1-v)*256.0)
  end
  return mesh
end

