
-- earth

viewer.mode=FULLSCREEN

function setup() 
    textMode(CORNER)
    assert(OrbitViewer, "Please include Cameras as a dependency")        
    scene = craft.scene()
    v=scene.camera:add(OrbitViewer, vec3(0,0,0), 500, 0, 3000)
    v.ry=220  
    image=readImage(asset.map)
    earth=icoSphere(vec3(0,0,0),100,5,false,true,1,image)
end

function draw()
    update(DeltaTime)
    scene:draw()
end

function update(dt)
    scene:update(dt)
    earth.rotation = quat.eulerAngles(-90,0,0)
end

function icoSphere(pos,size,level,flat,inside,material,image)
    local s=scene:entity()
    s.position=pos
    s.model=craft.model.icosphere(size,level,flat)  -- create icosphere
    s.material=craft.material(asset.builtin.Materials.Basic) 
    icoTexture(s,inside,image)
    return s
end

function icoTexture(sph,inside,img)
    local seam=0
    local ax,bx,cx,ay,by,cy,c,lat,lon  
    local posTab={}
    local pTab,cTab,nTab,llTab,uvTab,colTab,norTab,iTab={},{},{},{},{},{},{},{}
    local deg=math.deg
    local asin=math.asin
    local atan=math.atan
    sph.material.map=img 
    
    -- create tables for rounded icospheres        
    if not flat then
        iTab=sph.model.indices
        pTab=sph.model.positions
        cTab=sph.model.colors
        nTab=sph.model.normals  
        for a,b in pairs(iTab) do
            posTab[a]=pTab[b]
            colTab[a]=cTab[b]
            norTab[a]=nTab[b]
            iTab[a]=a
        end
    end 
    
    -- convert sphere positions to latitude and longitude
    for a,b in pairs(posTab) do
        c=b:normalize()
        lat=deg(asin(c.z))+90
        lon=deg(atan(c.y,c.x))
        llTab[a]=vec2(lon,lat)      -- save lon, lat in table
        if lon//1==-149 then        -- get exact value of seam
            seam=lon
        end
    end 
    
    -- shift points on the left side of the seam to the right side 
    for a,b in pairs(llTab) do        
        b.x=b.x-seam
        if b.x<-.01 then
            b.x=b.x+360
        end
    end 
    
    -- shift individual points of triangle if needed  
    for z=1,#llTab,3 do
        ax,ay=llTab[z].x,llTab[z].y
        bx,by=llTab[z+1].x,llTab[z+1].y
        cx,cy=llTab[z+2].x,llTab[z+2].y
        if ax>250 or bx>250 or cx>250 then
            if ax<.01 then 
                ax=360
            end
            if bx<.01 then
                bx=360
            end
            if cx<.01 then
                cx=360
            end  
        end 
        if ay==0 or ay==180 then
            ax=(bx+cx)*.5
        elseif by==0 or by==180 then
            bx=(ax+cx)*.5
        elseif cy==0 or cy==180 then
            cx=(ax+bx)*.5
        end  
        
        -- create uv table
        uvTab[z]=vec2(ax/360,ay/180)
        uvTab[z+1]=vec2(bx/360,by/180)
        uvTab[z+2]=vec2(cx/360,cy/180)
    end 
    
    -- reset tables 
    sph.model.uvs=uvTab
    
    -- flat shows the triangles that make the sphere
    if not flat then
        sph.model.indices=iTab
        sph.model.positions=posTab
        sph.model.colors=colTab
        sph.model.normals=norTab
    end
    
    --update indices table for inside view    
    if inside then
        iTab=sph.model.indices
        for z=#sph.model.indices,1,-1 do
            iTab[#iTab+1]=iTab[z]
        end
        sph.model.indices=iTab
    end
end
