Skip to content

Instantly share code, notes, and snippets.

@tnlogy
Created March 12, 2013 19:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tnlogy/5146337 to your computer and use it in GitHub Desktop.
Save tnlogy/5146337 to your computer and use it in GitHub Desktop.
IsoSphere with texture mapping
--# Main
-- IsoSphere
-- Use this function to perform your initial setup
function setup()
parameter.integer("Divisions", 0,5,1, createSphere)
parameter.number("H",-10,10,0)
R = 0
end
function createSphere()
is = IsoSphere(Divisions)
ga = IsoSphere(4)
ga.m.shader = nil
ga.m.texture = readImage("Documents:Galaxy")
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
camera(0,H,20, 0,0,0)
perspective(45)
rotate(R, 0,1,0)
is:draw()
scale(100)
ga:draw()
end
function touched(touch)
if touch.state == MOVING then
R = R + touch.deltaX
end
end
--# IsoSphere
-- Based on http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html
IsoSphere = class()
function IsoSphere:init(divisions)
local t = (1.0 + math.sqrt(5.0)) / 2.0;
local vs = {
vec3(-1,t,0),vec3(1,t,0),vec3(-1,-t,0),vec3(1,-t,0),
vec3(0,-1,t),vec3(0,1,t),vec3(0,-1,-t),vec3(0,1,-t),
vec3(t,0,-1),vec3(t,0,1),vec3(-t,0,-1),vec3(-t,0,1)
}
local ts = {
vs[1],vs[12],vs[6], -- 5 faces around vs[1]
vs[1],vs[6],vs[2],
vs[1],vs[2],vs[8],
vs[1],vs[8],vs[11],
vs[1],vs[11],vs[12],
vs[2],vs[6],vs[10], -- 5 adjacent faces
vs[6],vs[12],vs[5],
vs[12],vs[11],vs[3],
vs[11],vs[8],vs[7],
vs[8],vs[2],vs[9],
vs[4],vs[10],vs[5], -- 5 faces around vs[4]
vs[4],vs[5],vs[3],
vs[4],vs[3],vs[7],
vs[4],vs[7],vs[9],
vs[4],vs[9],vs[10],
vs[5],vs[10],vs[6], -- 5 adjacent faces
vs[3],vs[5],vs[12],
vs[7],vs[3],vs[11],
vs[9],vs[7],vs[8],
vs[10],vs[9],vs[2]
}
ts = self:divide(divisions or 0, ts)
self.m = mesh()
self.m.shader = lightShader
self.m.vertices = ts
self.m:setColors(255,255,255,255)
local nor = self.m:buffer("normal")
nor:resize(#ts)
local uvs = {}
local calcUV = function(v1, v2, v3)
local diff = function(a,b)
a = (b - a)/math.pi
if math.abs(a) >= 1 then
if a >= 0 then a = a - 2 else a = a + 2 end
end
return a
end
local a = math.atan2(v1.z,-v1.x)
local b = math.asin(-v1.y)
local uv1 = vec2(.5 + a/(math.pi*2), .5 - b/math.pi)
local uv2 = vec2(uv1.x + diff(a, math.atan2(v2.z,-v2.x))/2,
uv1.y - diff(b, math.asin(-v2.y)))
local uv3 = vec2(uv1.x + diff(a, math.atan2(v3.z,-v3.x))/2,
uv1.y - diff(b, math.asin(-v3.y)))
return uv1,uv2,uv3
end
for i=1,#ts,3 do
local v1,v2 = ts[i]:normalize(),ts[i+1]:normalize()
local v3 = ts[i+2]:normalize()
local uv1,uv2,uv3 = calcUV(v1,v2,v3)
nor[i],nor[i+1],nor[i+2] = v1,v2,v3
table.insert(uvs, uv1)
table.insert(uvs, uv2)
table.insert(uvs, uv3)
end
self.m.texCoords = uvs
-- http.request(
-- 'http://www.evl.uic.edu/pape/data/Earth/2048/PathfinderMap.jpg',
-- function(data) self.m.texture = data end)
self.m.texture = readImage("Documents:Earth")
end
function IsoSphere:divide(divisions, ts)
local mp = function (a, b) -- mid point
return ((a+b)/2)
end
for i=1,divisions do
local vs = {}
for j=1,#ts,3 do
local v1,v2,v3 = ts[j],ts[j+1],ts[j+2]
local a,b,c = mp(v1,v2),mp(v2,v3),mp(v3,v1)
local nvs = {v1,a,c, v2,b,a, v3,c,b, a,b,c}
for k,v in ipairs(nvs) do
table.insert(vs,v:normalize()*2)
end
end
ts = vs
end
return ts
end
function IsoSphere:draw()
if self.m.shader then
self.m.shader.light = vec3(-Gravity.x,-Gravity.y,0)
end
self.m:draw()
end
--# LightShader
lightShader = shader()
lightShader.vertexProgram = [[
uniform mat4 modelViewProjection;
uniform vec3 light;
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
attribute vec3 normal;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
void main()
{
vColor = color;
vTexCoord = vec2(texCoord.x,texCoord.y);
lowp vec4 nor = modelViewProjection * vec4(normal,0);
lowp float vShade = (dot(nor.xyz,light)+0.2)/1.2;
if (vShade >1.0) {vShade=1.0;}
if (vShade <0.1) {vShade=0.1;}
vColor.rgb = vColor.rgb * vShade;
gl_Position = modelViewProjection * position;
}
]]
lightShader.fragmentProgram = [[
uniform lowp sampler2D texture;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
void main()
{
gl_FragColor = texture2D(texture, vTexCoord)* vColor;
}
]]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment