Created
July 21, 2013 11:32
-
-
Save thatfool/6048305 to your computer and use it in GitHub Desktop.
ParaSurf Release v1.0.3 -Parametric Surfaces in Codea
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
ParaSurf Tab Order Version: 1.0.3 | |
------------------------------ | |
This file should not be included in the Codea project. | |
#Main | |
#ParaSurf |
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
-- Display a few parametric surfaces | |
VERSION = "1.0.3" | |
PROJECTNAME = "ParaSurf" | |
function setup() | |
autoGist = AutoGist(PROJECTNAME,"Parametric Surfaces in Codea",VERSION,false) | |
autoGist:backup(true) | |
displayMode(FULLSCREEN) | |
sphere = ParaSphere(1) | |
sphere.color = color(253, 255, 0, 255) | |
torus = ParaTorus(1) | |
torus.color = color(242, 116, 27, 255) | |
supersphere = ParaSuperellipsoid(1) | |
supersphere.color = color(170, 220, 45, 255) | |
supertorus = ParaSupertoroid(1) | |
supertorus.color = color(60,150,240,255) | |
supersphere2 = ParaSuperellipsoid(1) | |
supersphere2.n1 = 1.7 | |
supersphere2.n2 = 1.7 | |
supersphere2.color = color(59, 240, 209, 255) | |
trefoil = ParaTrefoil(1) | |
trefoil.color = color(240,60,150,255) | |
cyl1 = ParaCylinder(0.75) | |
cyl1.color = color(39, 217, 155, 255) | |
cyl2 = ParaSupercylinder(0.75) | |
cyl2.color = color(119, 44, 158, 255) | |
cyl3 = ParaSupercylinder(0.75) | |
cyl3.n = 1.7 | |
cyl3.color = color(231, 25, 36, 255) | |
grid = { | |
{ cyl3, supersphere2, trefoil }, | |
{ cyl2, supersphere, supertorus }, | |
{ cyl1, sphere, torus }, | |
} | |
shadr = shader([[ | |
attribute vec4 position; | |
attribute vec3 normal; | |
attribute vec3 color; | |
uniform mat4 modelViewProjection; | |
varying vec3 eyenormal; | |
varying vec3 diffuse; | |
void main(void) | |
{ | |
eyenormal = mat3(modelViewProjection) * normal; | |
diffuse = color; | |
gl_Position = modelViewProjection * position; | |
} | |
]], [[ | |
uniform highp vec3 light; | |
varying mediump vec3 eyenormal; | |
varying lowp vec3 diffuse; | |
void main(void) | |
{ | |
highp vec3 N = normalize(eyenormal); | |
highp vec3 L = normalize(light); | |
highp vec3 E = vec3(0, 0, 1); | |
highp vec3 H = normalize(L + E); | |
highp float df = max(0.0, dot(N, L)) * 0.3; | |
highp float sf = max(0.0, dot(N, H)); | |
sf = pow(sf, 250.0); | |
if(abs(N.z) < 0.2) sf = sf + (1.0 - abs(N.z)*(1.0/0.2)); | |
sf = sf * 0.5; | |
lowp vec3 color = vec3(1,1,1) * 0.7 * diffuse + df * diffuse + sf * vec3(1,1,1); | |
gl_FragColor = vec4(min(1.0,color.x), min(1.0,color.y), min(1.0,color.z), 1.0); | |
} | |
]] | |
) | |
shadr.light = vec3(0,1500,1000) | |
rx, ry = 0, 0 | |
end | |
function draw() | |
background(49, 49, 49, 255) | |
pushMatrix() | |
resetMatrix() | |
perspective(90, WIDTH/HEIGHT) | |
camera(0,0,-2, 0,0,0, 0,1,0) | |
rotate(rx, 1, 0, 0) | |
rotate(ry, 0, 1, 0) | |
frame = (frame or 0) + 1 | |
for y = 1, #grid do | |
for x = 1, #grid[y] do | |
pushMatrix() | |
translate(x-1-(#grid[y]-1)/2, y-1-(#grid-1)/2, 0) | |
scale(0.75) | |
rotate(frame, 0, 1, 0) | |
local p = grid[y][x] | |
local m = p:paramesh() | |
m.shader = shadr | |
m:draw() | |
popMatrix() | |
end | |
end | |
popMatrix() | |
end | |
function touched(touch) | |
if tid then | |
if touch.state == ENDED then | |
tid = nil | |
tweenid = tween(0.2, _G, {rx=0,ry=0}) | |
else | |
ry = ry - (tx - touch.x)*0.1 | |
rx = rx - (ty - touch.y)*0.1 | |
tx = touch.x | |
ty = touch.y | |
end | |
elseif touch.state == BEGAN then | |
tid = touch.id | |
tx = touch.x | |
ty = touch.y | |
if tweenid then | |
tween.stop(tweenid) | |
tweenid = nil | |
end | |
end | |
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
-- Generate meshes for parametric surfaces | |
-- | |
-- Parts adapted from code in | |
-- iPhone 3D Programming by Philip Rideout, O’Reilly, ISBN 978-0-596-80482-4. | |
ParaSurf = class() | |
function ParaSurf:init() | |
self.divx = 32 | |
self.divy = 32 | |
self.maxx = 100 | |
self.maxy = 100 | |
end | |
function ParaSurf:sgn(x) | |
if x < 0 then return -1 | |
elseif x > 0 then return 1 | |
end | |
return 0 | |
end | |
function ParaSurf:eval(x, y, wrap) | |
if wrap then | |
if x < 0 then x = x + self.maxx end | |
if y < 0 then y = y + self.maxy end | |
if x > self.maxx then x = x - self.maxx end | |
if y > self.maxy then y = y - self.maxy end | |
end | |
return self:calculate(x,y) | |
end | |
function ParaSurf:calculate(x, y) | |
return vec3(x,y,0) | |
end | |
function ParaSurf:normal(x, y) | |
local v, v1, v2 | |
local s = 0.001 | |
if x + s >= self.maxx then x = x - s end | |
if y + s >= self.maxy then y = y - s end | |
if x <= s then x = x + s end | |
if y <= s then y = y + s end | |
v = self:eval(x, y, true) | |
v1 = self:eval(x+s, y, true)-v | |
v2 = self:eval(x, y+s, true)-v | |
return v1:cross(v2):normalize() | |
end | |
function ParaSurf:paramesh(rebuild) | |
local m | |
if rebuild or not self.mesh then m = mesh() | |
else return self.mesh end | |
local v = {} | |
local n = {} | |
for y = 0, self.divy-2 do | |
for x = 0, self.divx-2 do | |
x1 = ((x+self.divx)%(self.divx) * self.maxx)/(self.divx-1) | |
y1 = ((y+self.divy)%(self.divy) * self.maxy)/(self.divy-1) | |
x2 = ((x+1)%(self.divx) * self.maxx)/(self.divx-1) | |
y2 = ((y+self.divy)%(self.divy) * self.maxy)/(self.divy-1) | |
x3 = ((x+1)%(self.divx) * self.maxx)/(self.divx-1) | |
y3 = ((y+1)%(self.divy) * self.maxy)/(self.divy-1) | |
x4 = ((x+self.divx)%(self.divx) * self.maxx)/(self.divx-1) | |
y4 = ((y+1)%(self.divy) * self.maxy)/(self.divy-1) | |
v1 = self:eval(x1, y1, x, y) | |
v2 = self:eval(x2, y2, x, y) | |
v3 = self:eval(x3, y3, x, y) | |
v4 = self:eval(x4, y4, x, y) | |
table.insert(v, v1) | |
table.insert(v, v2) | |
table.insert(v, v3) | |
table.insert(v, v1) | |
table.insert(v, v3) | |
table.insert(v, v4) | |
n1 = self:normal(x1, y1, x, y) | |
n2 = self:normal(x2, y2, x, y) | |
n3 = self:normal(x3, y3, x, y) | |
n4 = self:normal(x4, y4, x, y) | |
table.insert(n, n1) | |
table.insert(n, n2) | |
table.insert(n, n3) | |
table.insert(n, n1) | |
table.insert(n, n3) | |
table.insert(n, n4) | |
end | |
end | |
m.vertices = v | |
m.normals = n | |
m:setColors(self.color or color(200)) | |
self.mesh = m | |
return m | |
end | |
ParaSphere = class(ParaSurf) | |
function ParaSphere:init(radius) | |
ParaSurf.init(self) | |
self.maxx = math.pi | |
self.maxy = math.pi*2 | |
self.radius = (radius or 1)/2 | |
end | |
function ParaSphere:calculate(u, v) | |
local x = self.radius * math.sin(u) * math.cos(v) | |
local y = self.radius * math.cos(u) | |
local z = self.radius * -math.sin(u) * math.sin(v) | |
return vec3(x,y,z) | |
end | |
ParaSuperellipsoid = class(ParaSphere) | |
function ParaSuperellipsoid:init(radius) | |
ParaSphere.init(self, radius) | |
self.n1 = 0.5 | |
self.n2 = 0.5 | |
end | |
function ParaSuperellipsoid:calculate(u, v) | |
local x = self.radius * math.pow(math.abs(math.sin(u)),self.n1) * math.pow(math.abs(math.cos(v)),self.n2) * self:sgn(math.sin(u)) * self:sgn(math.cos(v)) | |
local y = self.radius * math.pow(math.abs(math.cos(u)),self.n1) * self:sgn(math.cos(u)) | |
local z = self.radius * -math.pow(math.abs(math.sin(u)),self.n1) * math.pow(math.abs(math.sin(v)),self.n2) * self:sgn(math.sin(u)) * self:sgn(math.sin(v)) | |
return vec3(x,y,z) | |
end | |
ParaTorus = class(ParaSurf) | |
function ParaTorus:init(radius) | |
ParaSurf.init(self) | |
self.maxx = math.pi * 2 | |
self.maxy = math.pi * 2 | |
self.radius = radius/2-radius/6 | |
self.rinner = radius/6 | |
end | |
function ParaTorus:calculate(u, v) | |
local x = (self.radius + self.rinner*math.cos(v)) * math.cos(u) | |
local y = (self.radius + self.rinner*math.cos(v)) * math.sin(u) | |
local z = self.rinner * math.sin(v) | |
return vec3(x,y,z) | |
end | |
ParaSupertoroid = class(ParaTorus) | |
function ParaSupertoroid:init(radius) | |
ParaTorus.init(self, radius) | |
self.n1 = 0.5 | |
self.n2 = 0.5 | |
end | |
function ParaSupertoroid:calculate(u, v) | |
local x = (self.radius + self.rinner*math.pow(math.abs(math.cos(v)),self.n1) * self:sgn(math.cos(v))) * math.pow(math.abs(math.cos(u)),self.n2) * self:sgn(math.cos(u)) | |
local y = (self.radius + self.rinner*math.pow(math.abs(math.cos(v)),self.n1) * self:sgn(math.cos(v))) * math.pow(math.abs(math.sin(u)),self.n2) * self:sgn(math.sin(u)) | |
local z = self.rinner * math.pow(math.abs(math.sin(v)),self.n1) * self:sgn(math.sin(v)) | |
return vec3(x,y,z) | |
end | |
ParaTrefoil = class(ParaSurf) | |
function ParaTrefoil:init(radius) | |
ParaSurf.init(self) | |
self.divx = self.divx * 2 | |
self.divy = self.divy / 2 | |
self.maxx = math.pi*2 | |
self.maxy = math.pi*2 | |
self.radius = (radius or 1)/2 | |
end | |
function ParaTrefoil:calculate(dx, dy) | |
local a, b, c, d = 0.5, 0.3, 0.5, 0.25 | |
local u = (math.pi*2 - dx) * 2 | |
local v = dy | |
local r = a + b * math.cos(1.5 * u) | |
local x = r * math.cos(u) | |
local y = r * math.sin(u) | |
local z = c * math.sin(1.5 * u) | |
local dv = vec3( | |
-1.5 * b * math.sin(1.5 * u) * math.cos(u) - (a + b * math.cos(1.5 * u)) * math.sin(u), | |
-1.5 * b * math.sin(1.5 * u) * math.sin(u) + (a + b * math.cos(1.5 * u)) * math.cos(u), | |
1.5 * c * math.cos(1.5 * u)) | |
local q = dv:normalize() | |
local qvn = vec3(q.y, -q.x, 0):normalize() | |
local ww = q:cross(qvn) | |
local range = vec3( | |
x + d * (qvn.x * math.cos(v) + ww.x * math.sin(v)), | |
y + d * (qvn.y * math.cos(v) + ww.y * math.sin(v)), | |
z + d * ww.z * math.sin(v)) | |
return range * self.radius | |
end | |
ParaCylinder = class(ParaSurf) | |
function ParaCylinder:init(radius) | |
ParaSurf.init(self) | |
self.maxx = math.pi | |
self.divx = 4 | |
self.maxy = math.pi*2 | |
self.radius = (radius or 1)/2 | |
end | |
function ParaCylinder:normal(u, v, uu, vv) | |
if uu == 1 then | |
local n = self:calculate(u,v,uu,vv) | |
n.y = 0 | |
return n:normalize() | |
end | |
return ParaSurf.normal(self, u, v) | |
end | |
function ParaCylinder:calculate(u, v) | |
local x = self.radius * math.sin(u) * math.cos(v) | |
local y = (self.radius * math.cos(u) < 0) and -self.radius or self.radius | |
local z = self.radius * -math.sin(u) * math.sin(v) | |
return vec3(x,y,z) | |
end | |
ParaSupercylinder = class(ParaCylinder) | |
function ParaSupercylinder:init(radius) | |
ParaCylinder.init(self, radius) | |
self.n = 0.2 | |
end | |
function ParaSupercylinder:calculate(u, v) | |
local x = self.radius * math.pow(math.abs(math.sin(u)),self.n) * math.pow(math.abs(math.cos(v)),self.n) * self:sgn(math.sin(u)) * self:sgn(math.cos(v)) | |
local y = (self.radius * math.cos(u) < 0) and -self.radius or self.radius | |
local z = self.radius * -math.pow(math.abs(math.sin(u)),self.n) * math.pow(math.abs(math.sin(v)),self.n) * self:sgn(math.sin(u)) * self:sgn(math.sin(v)) | |
return vec3(x,y,z) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment