Skip to content

Instantly share code, notes, and snippets.

@dermotbalson

dermotbalson/gist:7820304

Last active Dec 30, 2015
Embed
What would you like to do?
3D object viewer test
--# Main
function setup()
models={"Cessna.3D","Shuttle6.3D","TieFighter.3D","LunarModule.3D","F117.3D","ME262.3D","X-Wing.3D",
"Chair.3D"}
urls={
'https://gist.github.com/dermotbalson/7819845/raw/3b9ef8ff5264fcdda9babe2ecf9359d78b540879/3D_obj',
'https://gist.github.com/dermotbalson/7820337/raw/e055b56c8b43712e4f6bdb95b2711ccb2f312bba/gistfile1.txt',
'https://gist.github.com/dermotbalson/7820408/raw/4accb82895cbf746b030c6c27a57d5ace5b31158/gistfile1.txt',
'https://gist.github.com/dermotbalson/7820478/raw/7c0e81c732627c5a68980b4487f3bf0f6eac0af2/gistfile1.txt',
'https://gist.github.com/dermotbalson/7822315/raw/508edfdd316fad8344bee18f5ff856a68834474d/gistfile1.txt',
'https://gist.github.com/dermotbalson/7822370/raw/aa432a6b7c925aa392d9d83398f8fd9147e5c0a9/gistfile1.txt',
'https://gist.github.com/dermotbalson/7822630/raw/25a1721b50375b2ef92419fa0c9187d5077cdb47/gistfile1.txt',
'https://gist.github.com/dermotbalson/7822709/raw/b68a48165007baa92895b3e0bdb681e183c1aee5/gistfile1.txt'
}
parameter.integer("Choose",1,#models,2)
parameter.action("Load",LoadData)
parameter.integer("Zoom",1,100,50)
parameter.boolean("AutoRotate",true)
parameter.integer("X",-180,180,0)
parameter.integer("Y",-180,180,0)
parameter.integer("Z",-180,180,0)
for i=1,#models do
print(i,models[i])
end
print("Don't forget to use the Zoom parameter!")
LoadData()
end
function LoadData()
M=nil
dataFile=models[Choose]
loadStatus=nil
local file = os.getenv("HOME").."/Documents/"..dataFile
local f,err = io.open(file,"r")
if not err then
local s = f:read("*all")
io.close(f)
loadstring(s)()
loadStatus=true
setup2()
else
print("Downloading "..dataFile)
http.request(urls[Choose],GotData)
end
end
function GotData(data)
print("Saving "..dataFile)
local file = os.getenv("HOME").."/Documents/"..dataFile
local f,err = io.open(file,"w")
if not err then
f:write(data)
f:close()
else
print(dataFile.. "save error = "..err)
end
LoadData()
end
function setup2()
--the vertices can be split into groups, each for a different part of the shuttle
--each has its own mesh and colour
--a simple shader provides some lighting
v={}
p={}
for i=1,#P,3 do
p[(i+2)/3]=vec3(P[i],P[i+1],P[i+2])
end
for i=1,#V do
v[i]=p[V[i]]
end
m={}
if M~=nil then
for i=1,#M do
local vv={}
local j
if i<#M then j=M[i+1][1]-1 else j=#v end
m[i]=mesh()
m[i].C2={}
local n=0
for k=M[i][1],j do
table.insert(vv,v[k])
n=n+1 m[i].C2[n]=GetColor(k)
end
m[i].vertices=vv
m[i].C1=M[i][2]
m[i]:setColors(m[i].C1)
end
else
m[1]=mesh()
vv={}
m[1].vertices=v
m[1].C2={}
for i=1,#v do
m[1].C2[i]=GetColor(i)
end
m[1].C1=color(255)
m[1]:setColors(m[1].C1)
end
for i=1,#m do --add lighting to each mesh
m[i].shader=shader(diffuseShader.vertexShader,diffuseShader.fragmentShader)
local d=0.8
m[i].shader.directColor=color(255*d,255*d,255*d)
m[i].shader.directDirection=vec4(-2,1,4,0):normalize()
local a=0.2
m[i].shader.ambientColor=color(255*a,255*a,255*a,255)
m[i].normals=CalculateAverageNormals(m[i].vertices,0)
m[i].shader.reflect=1
end
--rotate shuttle in all three directions
rot=vec3(0,0,0)
tween( 15, rot, { x = 360 }, { easing = tween.easing.linear, loop = tween.loop.pingpong } )
tween( 27, rot, { y = 360 }, { easing = tween.easing.linear, loop = tween.loop.pingpong } )
tween( 35, rot, { z = 360 }, { easing = tween.easing.linear, loop = tween.loop.pingpong } )
end
function draw()
if not loadStatus then return end
if touchPos then
if touchImg==nil then
touchImg=image(WIDTH,HEIGHT)
setContext(touchImg)
else
local a,b=touchImg:get(touchPos.x,touchPos.y)
print("Vertex="..a*256+b)
touchPos=nil
touchImg=nil
end
end
background(40, 40, 50)
perspective()
camera(0,0,Zoom,0,0,-Zoom)
pushMatrix()
if AutoRotate then
rotate(rot.x,1,0,0)
rotate(rot.y,0,1,0)
rotate(rot.z,0,0,1)
else
rotate(X,1,0,0)
rotate(Y,0,1,0)
rotate(Z,0,0,1)
end
for i=1,#m do
if touchPos then
m[i].shader.useIndex=true
m[i].colors=m[i].C2
else
m[i].shader.useIndex=false
m[i]:setColors(m[i].C1)
end
m[i].shader.mModel=modelMatrix() --part of lighting
m[i]:draw()
end
popMatrix()
if touchPos then setContext() end
end
function GetColor(n)
local b=math.fmod(n,256)
local a=(n-b)/255
return color(a,b,0)
end
function touched(t)
if t.state==BEGAN then
touchPos=vec2(t.x,t.y)
end
end
--# Shader
function CalculateNormals(vertices)
--this assumes flat surfaces, and hard edges between triangles
local norm = {}
for i=1, #vertices,3 do --calculate normal for each set of 3 vertices
local n = ((vertices[i+1] - vertices[i]):cross(vertices[i+2] - vertices[i])):normalize()
norm[i] = n --then apply it to all 3
norm[i+1] = n
norm[i+2] = n
end
return norm
end
function CalculateAverageNormals(vertices,f)
--average normals at each vertex
--first get a list of unique vertices, concatenate the x,y,z values as a key
local norm,unique= {},{}
for i=1, #vertices do
unique[vertices[i].x ..vertices[i].y..vertices[i].z]=vec3(0,0,0)
end
--calculate normals, add them up for each vertex and keep count
for i=1, #vertices,3 do --calculate normal for each set of 3 vertices
local n = (vertices[i+1] - vertices[i]):cross(vertices[i+2] - vertices[i])
for j=0,2 do
local v=vertices[i+j].x ..vertices[i+j].y..vertices[i+j].z
unique[v]=unique[v]+n
end
end
--calculate average for each unique vertex
for i=1,#unique do
unique[i] = unique[i]:normalize()
end
--now apply averages to list of vertices
for i=1, #vertices,3 do --calculate average
local n = (vertices[i+1] - vertices[i]):cross(vertices[i+2] - vertices[i])
for j=0,2 do
local m = unique[vertices[i+j].x ..vertices[i+j].y..vertices[i+j].z]
norm[i+j]=n*f+m*(1-f)
end
end
return norm
end
function CalculateAverageNormals0(vertices)
--average normals at each vertex
--first get a list of unique vertices, concatenate the x,y,z values as a key
local norm,unique= {},{}
for i=1, #vertices do
unique[vertices[i].x ..vertices[i].y..vertices[i].z]=vec3(0,0,0)
end
--calculate normals, add them up for each vertex and keep count
for i=1, #vertices,3 do --calculate normal for each set of 3 vertices
local n = (vertices[i+1] - vertices[i]):cross(vertices[i+2] - vertices[i])
for j=0,2 do
local v=vertices[i+j].x ..vertices[i+j].y..vertices[i+j].z
unique[v]=unique[v]+n
end
end
--calculate average for each unique vertex
for i=1,#unique do
unique[i] = unique[i]:normalize()
end
--now apply averages to list of vertices
for i=1, #vertices do --calculate average
norm[i] = unique[vertices[i].x ..vertices[i].y..vertices[i].z]
end
return norm
end
diffuseShader={
vertexShader=[[
uniform mat4 modelViewProjection;
uniform mat4 mModel;
uniform vec4 directColor;
uniform vec4 directDirection;
attribute vec4 position;
attribute vec4 color;
attribute vec3 normal;
varying lowp vec4 vColor;
varying lowp vec4 vPosition;
varying lowp vec4 vNormal;
varying vec4 vDirectDiffuse;
void main()
{
vColor = color;
gl_Position = modelViewProjection * position;
vNormal = mModel * vec4( normal, 0.0 );
vec4 norm = normalize(vNormal);
vPosition = mModel * position;
vDirectDiffuse = directColor * max( 0.0, dot( norm, directDirection ));
}
]],
fragmentShader=[[
precision highp float;
uniform vec4 ambientColor;
uniform float reflect;
uniform bool useIndex;
varying lowp vec4 vColor;
varying lowp vec4 vPosition;
varying lowp vec4 vNormal;
varying vec4 vDirectDiffuse;
vec4 normalizedNormal = normalize(vNormal);
void main()
{
if (useIndex) gl_FragColor=vColor;
else {
vec4 ambient = vColor * ambientColor;
vec4 diffuse = vColor * vDirectDiffuse;
vec4 totalColor = reflect * (ambient + diffuse);
totalColor.a=1.;
gl_FragColor=totalColor;
}
}
]]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.