Last active
August 29, 2015 14:13
-
-
Save dermotbalson/11696d0b6bd4600bf6de to your computer and use it in GitHub Desktop.
Touch code plane - ver 4
This file contains 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
function setup() | |
--set up details for a couple of pictures | |
pics={ | |
{name="red",pos=vec3(-100,-200,-250),size=vec3(400,600,1),rotation=vec3(45,0,20),colr=color(255,0,0)}, | |
{name="yellow",pos=vec3(100,-100,-400),size=vec3(400,600,1),rotation=vec3(-45,30,0),colr=color(255,255,0)} | |
} | |
--add them to the Touch class (so we can detect touches) | |
for _,p in pairs(pics) do | |
--we need to provide some kind of id, so the Touch class can tell us which object was touched | |
--we also need to provide the position (of the centre of the picture), and its size, both vec3 | |
--the Touch class gives us back a reference which we need to store, for each picture | |
--because we'll need it in draw | |
p.tch=Touch(p,p.pos,p.size) | |
end | |
end | |
function draw() | |
background(50) | |
perspective() | |
camera(0,0,1000,0,0,-1) | |
for _,p in pairs(pics) do | |
pushMatrix() | |
--you can translate and rotate any way you want | |
translate(p.pos.x,p.pos.y,p.pos.z) | |
if p.rotation.x~=0 then rotate(p.rotation.x,1,0,0) end | |
if p.rotation.y~=0 then rotate(p.rotation.y,0,1,0) end | |
if p.rotation.z~=0 then rotate(p.rotation.z,0,0,1) end | |
--draw the image any way you want | |
fill(p.colr) | |
rect(-p.size.x/2,-p.size.y/2,p.size.x,p.size.y) | |
--next, is why we had to store the reference received back from Touch, because now | |
--we need to tell the Touch class about the translations and rotations for this picture | |
--this must be done for each picture | |
--you only really need to do this when something changes, not necessarily every frame | |
p.tch:storeMatrix() | |
popMatrix() | |
end | |
end | |
function touched(t) | |
local touches={} | |
if t.state==ENDED then | |
--this is all you need to find out which object was touched | |
--it returns the picture id (which you provided initially) | |
--as well as the touch position (x,y) | |
--and the z value of the touch, if you want it | |
local id,tc,d=Touch:PictureIsTouchedBy(t) | |
if id then print(id.name,tc) end | |
end | |
end | |
------ touch code below ---- | |
Touch=class() | |
Touch.list={} | |
function Touch:init(id,pos,size) | |
self.id=id --string or number (optional) | |
self.pos=pos --vec3 | |
self.size=size --vec2 | |
end | |
function Touch:storeMatrix() | |
self.model=modelMatrix() | |
self.matrix=modelMatrix() * viewMatrix() * projectionMatrix() | |
if Touch.list[self.id] then Touch.list={} end | |
Touch.list[self.id]=self | |
end | |
function Touch:PictureIsTouchedBy(t) | |
local item, tc, dist, d | |
for _,L in pairs(Touch.list) do | |
local p,s=L.pos,L.size | |
tc = screentoplane(t, vec3(0,0,0), vec3(1,0,0), vec3(0,1,0), L.matrix) | |
tc=vec2(tc.x+0.5*s.x,tc.y+0.5*s.y) | |
if tc.x<0 or tc.x>s.x or tc.y<0 or tc.y>s.y then --didn't touch, do nothing | |
else | |
L.tc=tc --store touch position | |
--now get z value of touch | |
local a=L.model:translate(tc.x-s.x/2,tc.y-s.y/2,0) | |
d=a[15] | |
--keep track of closest picture | |
if not item or dist>d then item,dist=L,d end | |
end | |
end | |
if item then return item.id,item.tc,d end | |
end | |
-- Compute the cofactor matrix of a 3x3 matrix, entries | |
-- hard-coded for efficiency. | |
-- The cofactor differs from the inverse by a scale factor, but | |
-- as our matrices are only well-defined up to scale, this | |
-- doen't matter. | |
function cofactor3(m) | |
return { | |
vec3( | |
m[2].y * m[3].z - m[3].y * m[2].z, | |
m[3].y * m[1].z - m[1].y * m[3].z, | |
m[1].y * m[2].z - m[2].y * m[1].z | |
), | |
vec3( | |
m[2].z * m[3].x - m[3].z * m[2].x, | |
m[3].z * m[1].x - m[1].z * m[3].x, | |
m[1].z * m[2].x - m[2].z * m[1].x | |
), | |
vec3( | |
m[2].x * m[3].y - m[3].x * m[2].y, | |
m[3].x * m[1].y - m[1].x * m[3].y, | |
m[1].x * m[2].y - m[2].x * m[1].y | |
) | |
} | |
end | |
-- Given a plane in space, this computes the transformation | |
-- matrix from that plane to the screen | |
function __planetoscreen(o,u,v,A) | |
A = A or modelMatrix() * viewMatrix() * projectionMatrix() | |
o = o or vec3(0,0,0) | |
u = u or vec3(1,0,0) | |
v = v or vec3(0,1,0) | |
-- promote to 4-vectors | |
o = vec4(o.x,o.y,o.z,1) | |
u = vec4(u.x,u.y,u.z,0) | |
v = vec4(v.x,v.y,v.z,0) | |
local oA, uA, vA | |
oA = A*o | |
uA = A*u | |
vA = A*v | |
oA = applymatrix4(o,A) | |
uA = applymatrix4(u,A) | |
vA = applymatrix4(v,A) | |
return { vec3(uA[1], uA[2], uA[4]), | |
vec3(vA[1], vA[2], vA[4]), | |
vec3(oA[1], oA[2], oA[4])} | |
end | |
-- Given a plane in space, this computes the transformation | |
-- matrix from the screen to that plane | |
function screentoplane(t,o,u,v,A) | |
A = A or modelMatrix() * viewMatrix() * projectionMatrix() | |
o = o or vec3(0,0,0) | |
u = u or vec3(1,0,0) | |
v = v or vec3(0,1,0) | |
t = t or CurrentTouch | |
local m = __planetoscreen(o,u,v,A) | |
m = cofactor3(m) | |
local ndc = vec3((t.x/WIDTH - .5)*2,(t.y/HEIGHT - .5)*2,1) | |
local a | |
a = applymatrix3(ndc,m) | |
if (a[3] == 0) then return end | |
a = vec2(a[1], a[2])/a[3] | |
return o + a.x*u + a.y*v | |
end | |
-- This computes a frame in which the first vector is along | |
-- the "touch ray" and the other two are in the orthogonal plane | |
-- (but the whole frame is not guaranteed to be orthogonal) | |
function screenframe(t,A) | |
A = A or modelMatrix() * viewMatrix() * projectionMatrix() | |
t = t or CurrentTouch | |
local u,v,w,x,y | |
u = vec3(A[1],A[5],A[9]) | |
v = vec3(A[2],A[6],A[10]) | |
w = vec3(A[4],A[8],A[12]) | |
x = (t.x/WIDTH - .5)*2 | |
y = (t.y/HEIGHT - .5)*2 | |
u = u - x*w | |
v = v - y*w | |
return u:cross(v),u,v | |
end | |
-- Apply a 3-matrix to a 3-vector | |
function applymatrix3(v,m) | |
return v.x * m[1] + v.y * m[2] + v.z * m[3] | |
end | |
-- Apply a 4-matrix to a 4-vector | |
function applymatrix4(v,m) | |
return vec4( | |
m[1]*v[1] + m[5]*v[2] + m[09]*v[3] + m[13]*v[4], | |
m[2]*v[1] + m[6]*v[2] + m[10]*v[3] + m[14]*v[4], | |
m[3]*v[1] + m[7]*v[2] + m[11]*v[3] + m[15]*v[4], | |
m[4]*v[1] + m[8]*v[2] + m[12]*v[3] + m[16]*v[4] | |
) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment