Skip to content

Instantly share code, notes, and snippets.

@RichardMN
Created February 17, 2013 19:35
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 RichardMN/4973013 to your computer and use it in GitHub Desktop.
Save RichardMN/4973013 to your computer and use it in GitHub Desktop.
LatheMesh - a factory class for creating rotated solids in Codea.
--# LatheMesh
-- LatheMesh
-- A factory class for creating solids based on rotating an outline series of points around
-- an axis.
-- Richard Martin-Nielsen, 2013
LatheMesh = class()
-- LatheMesh
outputVertices = false
LatheMesh = class()
LatheMesh.FLAT = 1
LatheMesh.SMOOTH = 2
function LatheMesh:buildMesh(segs)
local vlist = self.vlist
local col = self.color
local plist = {}
local clist = {}
local nlist = {}
local vcount = 0
local roti = math.pi*2 / segs
print ("roti",roti)
local lastv
for i,v in ipairs(vlist) do
if i ~= 1 then
local lp = v
local tl,tr,bl,br,normal,intensity, trc, trn
for s=1,segs do
local crs, crsn, srs, srsn
crs = math.cos(roti*s)
crsn = math.cos(roti*(s+1))
srs = math.sin(roti*s)
srsn = math.sin(roti*(s+1))
tl = vec3(lastv.x*crs-lastv.y*srs,
lastv.x*srs-lastv.y*crs,lastv.z)
tr = vec3(lastv.x*crsn-lastv.y*srsn,
lastv.x*srsn-lastv.y*crsn,lastv.z)
bl = vec3(v.x*crs-v.y*srs,
v.x*srs-v.y*crs,v.z)
br = vec3(v.x*crsn-v.y*srsn,
v.x*srsn-v.y*crsn,v.z)
--tr = vec3(lastv.x,lastv.y*math.cos(roti*(s+1)),lastv.y*math.sin(roti*(s+1)))
--bl = vec3(v.x,v.y*math.cos(roti*s),v.y*math.sin(roti*s))
--br = vec3(v.x,v.y*math.cos(roti*(s+1)),v.y*math.sin(roti*(s+1)))
table.insert(plist,tl)
table.insert(plist,tr)
table.insert(plist,bl)
if self.lighting == LatheMesh.FLAT then
normal = tr-tl
normal = normal:cross (tl-bl)
normal = normal:normalize ()
intensity = (normal:dot(self.lightd)*80 + 125) /255
local gl = color(intensity*col.r,intensity*col.g,intensity*col.b)
for i=1,3 do
table.insert(clist,gl)
table.insert(nlist,normal)
end
else
if vlist[i+1] == nil then
normal = vlist[i-1]-v
-- y' = y*cos q - z*sin q
--z' = y*sin q + z*cos q
--x' = x
normal = -vec3(normal.x,-normal.z,normal.y)
elseif vlist[i-1] == nil then
normal = vlist[i+1]-v
--normal = vec3(normal.y,-normal.x,0)
normal = vec3(normal.x,-normal.z,normal.y)
else
local v1,v2
v1 = (v-vlist[i-1])
--v1 = vec3(v1.y,-v1.x,0)
v1 = vec3(v1.x,-v1.z,v1.y)
v1 = v1:normalize()
v2 = (vlist[i+1]-v)
v2 = vec3(v2.x,-v2.z,v2.y)
v2 = v2:normalize()
-- print("v1,v2",v1,v2)
normal = v1+ v2
end
--normal = vec3(normal.x, normal.y*math.cos(roti*s),normal.y*math.sin(roti*s))
local rotnormal = -vec3(normal.x*crs-normal.y*srs,normal.x*srs-normal.y*crs,
normal.z)
rotnormal = rotnormal:normalize()
intensity = (rotnormal:dot(self.lightd)*80 + 125) /255
-- if intensity == 0 or intensity == math.huge then
-- print("inten=0",i,intensity,normal)
--end
local gl = color(intensity*col.r,intensity*col.g,intensity*col.b)
table.insert(clist, gl)
table.insert(nlist, rotnormal)
rotnormal = -vec3(normal.x*crsn-normal.y*srsn,normal.x*srsn-normal.y*crsn,
normal.z)
rotnormal = rotnormal:normalize()
intensity = (rotnormal:dot(self.lightd)*80 + 125) /255
if intensity == 0 then
print("inten=0",i,normal)
end
trc = color(intensity*col.r,intensity*col.g,intensity*col.b)
table.insert(clist, trc)
table.insert(nlist, rotnormal)
trn = rotnormal
-- leave bottom right colour to do in next set with next row of normals
-- save top right colour (trc) to reuse then
end
table.insert(plist,tr)
table.insert(plist,br)
table.insert(plist,bl)
if self.lighting == LatheMesh.FLAT then
normal = tr-br
normal = normal:cross (bl-br)
normal = normal:normalize ()
intensity = (normal:dot(self.lightd)*80 + 125) /255
local gl = color(intensity*col.r,intensity*col.g,intensity*col.b)
for i=1,3 do
table.insert(clist,gl)
table.insert(nlist,normal)
end
else
normal = v
if vlist[i+1] == nil then
normal = vlist[i]-vlist[i-1]
normal = vec3(normal.x,-normal.z,normal.y)
elseif vlist[i+2] == nil then
normal = vlist[i+1]-v
normal = vec3(normal.x,-normal.z,normal.y)
else
local v1,v2
--v1 = (vlist[i]-vlist[i+1])
v1 = (vlist[i+1]-vlist[i])
v1 = vec3(v1.x,-v1.z,v1.y)
v1 = v1:normalize()
v2 = (vlist[i+2]-vlist[i+1])
v2 = vec3(v2.x,-v2.z,v2.y)
v2 = v2:normalize()
normal = v1+ v2
--normal = vlist[i]-2*vlist[i+1]+vlist[i+2]
--normal = normal + vlist[i+2]-vlist[i+1]
--print("c",normal)
end
-- print(i,s,vlist[i-1],vlist[i],vlist[i+1],vlist[i+2])
local rotnormal = -vec3(normal.x*crs-normal.y*srs,normal.x*srs-normal.y*crs,
normal.z)
rotnormal = rotnormal:normalize()
intensity = (rotnormal:dot(self.lightd)*80 + 125) /255
if intensity == 0 then
print("blc:inten=0",i,normal)
end
local blc = color(intensity*col.r,intensity*col.g,intensity*col.b)
local bln = rotnormal
table.insert(clist,blc)
table.insert(nlist,rotnormal)
table.insert(clist,trc)
table.insert(nlist,trn)
rotnormal = -vec3(normal.x*crsn-normal.y*srsn,normal.x*srsn-normal.y*crsn,
normal.z)
rotnormal = rotnormal:normalize()
intensity = (rotnormal:dot(self.lightd)*80 + 125) /255
if intensity == 0 then
print("gl:inten=0",i,normal)
end
local gl = color(intensity*col.r,intensity*col.g,intensity*col.b)
table.insert(clist,gl)
table.insert(nlist,rotnormal)
table.insert(clist,blc)
table.insert(nlist,bln)
end
--print(vcount,lp)
vcount = vcount + 1
--rp.x = v.x
--rp.y = v.y*math.cos(roti*(s+1))
--rp.z = v.y*math.sin(roti*(s+1))
end
end
lastv = v
end
self.lmesh.vertices =plist
self.lmesh.colors = clist
self.lmesh.normals = nlist
print(table.maxn(plist),table.maxn(nlist))
local vmax = table.maxn(plist)
--print(vmax,table.maxn (self.lmesh.vertices))
end
function LatheMesh:init(vlist,col,segs)
self.lmesh= mesh()
--self.lv = vec3(1,1,1)
self.lighting = LatheMesh.SMOOTH
--self.lighting = LatheMesh.FLAT
self.lightd = vec3(1,1,1)
self.lightd = self.lightd:normalize()
self.color = col or color(255, 255, 255, 255)
self.vlist = vlist
self:buildMesh(segs)
--self.lmesh:setColors(color(255,0,0))
-- for i=1,vmax do
--self.lmesh:color(i,clist[i])
end
function LatheMesh:draw()
self.lmesh:draw()
end
function printVertexList(vl)
print("lm = {")
for i,v in ipairs(vl) do
print(string.format("\tvec3(%.2f,%.2f,%.2f),",v.x,v.y,v.z))
end
print("}")
end
function printVertexColors(vc)
print("lc = {")
for i,v in ipairs(vc) do
print(string.format("\tcolor(%.2f,%.2f,%.2f,%.2f),",v.r,v.g,v.b,v.a))
end
print("}")
end
--# Main
-- LatheMesh demonstration code
-- LatheMesh is a factory class for creating solids based on rotating an
-- outline series of points around an axis.
-- Richard Martin-Nielsen, 2013
-- Use this function to perform your initial setup
function setup()
parameter.integer("Size",50,500,150)
parameter.number("CamHeight", -500, 1000, 300)
parameter.number("Angle",-360, 360, 0)
parameter.number("FieldOfView", 10, 140, 45)
--iparameter("Lighting",1,2)
parameter.integer("Segments",3,36,12,rebuildMeshes)
parameter.boolean("useDiffuseShader",true)
outlines = {}
p = {vec3(0,25,0),vec3(0,50,25),vec3(0,100,50)}
table.insert(outlines,p)
p={}
for i=1,20 do
table.insert(p,vec3(0,5+25*math.sin(math.rad(i*15)),0+i*50))
end
table.insert(outlines,p)
p={}
for i = 0,10 do
table.insert(p,vec3(0,math.sin(i*math.pi/10)*50,math.cos(i*math.pi/10)*50))
end
table.insert(outlines,p)
p = {vec3(0,25,0),vec3(0,25,25),vec3(0,25,50),vec3(0,25,75)}
table.insert(outlines,p)
p={}
for i = 0,8 do
table.insert(p,vec3(0,math.sin(i*math.pi/10)*50,math.cos(i*math.pi/10)*50))
end
table.insert(p,vec3(0,50,-175))
table.insert(p,vec3(0,0,-175))
table.insert(outlines,p)
parameter.integer("Outline",1,table.maxn(outlines),rebuildMeshes)
-- p = {}
--p = {vec3(0,5,0),vec3(25,55,0)}
oldLighting = Lighting
oldOutline = Outline
--segs = 12
lm = LatheMesh(outlines[Outline],color(255,255,0),Segments)
lmf = LatheMesh(outlines[Outline],color(255,255,0),Segments)
lms = LatheMesh(outlines[Outline],color(255,255,0),Segments)
if useDiffuseShader then
lms.shader = shader("Documents:Diffuse Shader1")
end
lmf.lighting = LatheMesh.FLAT
lmf:buildMesh(Segments)
if outputVertices then
printVertexList(lm.lmesh.vertices)
end
--rebuildMeshes()
print(lm.lmesh.valid)
end
function rebuildMeshes()
if outlines ~= nil then
lm = LatheMesh(outlines[Outline],color(255,255,0),Segments)
lmf = LatheMesh(outlines[Outline],color(255,255,0),Segments)
lms = LatheMesh(outlines[Outline],color(255,255,0),Segments)
lmf.lighting = LatheMesh.FLAT
lmf:buildMesh(Segments)
end
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
--FieldOfView = 140
perspective(FieldOfView, WIDTH/HEIGHT)
scale(Size/150,Size/150,Size/150)
rotate(Angle)
-- Position the camera up and back, look at origin
camera(0,CamHeight,-300, 0,0,0, 0,1,0)
-- This sets the line thickness
strokeWidth(5)
if false then -- outline ~= oldOutline then
lm = LatheMesh(outlines[Outline],color(255,255,0),Segments)
lmf = LatheMesh(outlines[Outline],color(255,255,0),Segments)
lms = LatheMesh(outlines[Outline],color(255,255,0),Segments)
lmf.lighting = LatheMesh.FLAT
lmf:buildMesh(Segments)
oldOutline = outline
end
stroke(255, 0, 0, 255)
-- Do your drawing here
--translate(WIDTH/2,HEIGHT/2)
--scale(2
translate(-50,0,0)
lm:draw()
translate(100,0,0)
lmf:draw()
if useDiffuseShader then
translate(-50,50,0)
--lms.lmesh.shader = shader("Documents:Diffuse Shader1")
lms.lmesh.shader = shader(DiffuseShader1.Vertex,
DiffuseShader1.Fragment)
lms.lmesh.shader.m = modelMatrix()
local mit = modelMatrix()
mit = mit:transpose()
mit = mit:inverse()
lms.lmesh.shader.m_3x3_inv_transp = mit
lms.lmesh.shader.v = viewMatrix()
lms.lmesh.shader.p = projectionMatrix()
lms:draw()
end
end
DiffuseShader1 = {
Vertex = [[
//
// A basic vertex shader
//
//This is the current model * view * projection matrix
// Codea sets it automatically
uniform mat4 modelViewProjection;
//This is the current mesh vertex position, color and tex coord
// Set automatically
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
attribute vec3 normal;
//This is an output variable that will be passed to the fragment shader
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
uniform mat4 m, v, p;
uniform mat3 m_3x3_inv_transp;
varying vec4 mycolor;
struct lightSource
{
vec4 position;
vec4 diffuse;
};
lightSource light0 = lightSource(
vec4(-1.0, 1.0, -1.0, 0.0),
vec4(1.0, 1.0, 1.0, 1.0)
);
struct material
{
vec4 diffuse;
};
material mymaterial = material(vec4(1.0, 0.8, 0.8, 1.0));
void main(void)
{
mat4 mvp = p*v*m;
vec3 normalDirection = normalize(m_3x3_inv_transp * normal);
vec3 lightDirection = normalize(vec3(light0.position));
vec3 diffuseReflection
= vec3(light0.diffuse) * vec3(mymaterial.diffuse)
* max(0.0, dot(normalDirection, lightDirection));
mycolor = vec4(diffuseReflection, 1.0);
gl_Position = mvp * position;
}
]],
Fragment = [[
//
// A basic fragment shader
//
//Default precision qualifier
precision highp float;
//This represents the current texture on the mesh
uniform lowp sampler2D texture;
//The interpolated vertex color for this fragment
varying lowp vec4 vColor;
//The interpolated texture coordinate for this fragment
varying highp vec2 vTexCoord;
varying vec4 mycolor;
void main(void)
{
gl_FragColor = mycolor;
}
]]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment