반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리

Pinch Zoom Rotate 구현하기 - 9/11 -

2013. 2. 14. 21:35 | Posted by 솔웅


반응형
Posted on . Written by


Rotation


이제 display object를 회전시키는 기능을 적용하겠습니다. 기본적인 로직은 midpoint 주위로 각각의 tracking dot 이 얼마나 ratate 되었느냐를 판단하는것부터 시작해야 할 겁니다. 그 평균을 구해서 object 의 이전 .rotation 값에 그 차이를 더해 주어야겠죠. 이것을 하려면 이것을 계산하는 함수들을 몇개 더 추가 해야 겠네요.

왜냐하면 angle 을 계산하려면 특정 수학 공식을 대입해야 하거든요. 그리고 원 둘레의 두 포인트 사이의 가장 작은 angle 을 구하는 작업도 필요합니다. 이것은 tracking dot 이 회전한 것에 대한 angle 을 사용할 때 아주 중요하게 사용됩니다. 잘못하면 작은 각도 말고 큰 각도를 사용할 수 있거든요. 90도와 260도가 있다면 우리가 필요한 것은 90도 입니다.


sample9.lua

-- returns the degrees between (0,0) and pt (note: 0 degrees is 'east')
function angleOfPoint( pt )
local x, y = pt.x, pt.y
local radian = math.atan2(y,x)
local angle = radian*180/math.pi
if angle < 0 then angle = 360 + angle end
return angle
end
 
-- returns the degrees between two points (note: 0 degrees is 'east')
function angleBetweenPoints( a, b )
local x, y = b.x - a.x, b.y - a.y
return angleOfPoint( { x=x, y=y } )
end
 
-- returns the smallest angle between the two angles
-- ie: the difference between the two angles via the shortest distance
function smallestAngleDiff( target, source )
local a = target - source
if (a > 180) then
a = a - 360
elseif (a < -180) then
a = a + 360
end
return a
end

calcAvgScaling 함수에서 했던 것처럼 모든 tracking dot들이 midpoint 주위를 회전한 것에 대한 평균 값을 구하기 위해 calcAvgRotation 함수를 사용하고 그 안에서 위의 함수들을 사용할 겁니다. 그리고 tracking dot 각도들 사이의 차이들도 update 해야 합니다. 그리고 직전 각도들도 마찬가지구요. 다행히 midpoint 로부터의 거리와 관련해서는 이미 구현해 놨었습니다. 약간의 코드만 추가하면 될 것 같습니다.

-- calculates rotation amount based on the average change in tracking point rotation
local function calcAverageRotation( points )
local total = 0
for i=1, #points do
local point = points[i]
total = total + smallestAngleDiff( point.angle, point.prevAngle )
end
return total / #points
end
 
-- calculate each tracking dot's distance and angle from the midpoint
local function updateTracking( centre, points )
for i=1, #points do
local point = points[i]
point.prevAngle = point.angle
point.prevDistance = point.distance
point.angle = angleBetweenPoints( centre, point )
point.distance = lengthOf( centre, point )
end
end

이제 이 약간의 코드를 추가함으로서 rect:touch() 함수는 이미 began 과 ended  phases 에 해당 값들을 업데이트 하게 되었습니다. 이제 우리가 해야 할 일은 moved phase 안의 “rect” display object에 rotation 을 적용하는 것 뿐입니다. 이 기능은 tracking dot 이 하나 이상일 때에 적용되는 기능입니다. 이제 tracking dot들의 midpoint 주위의 회전값 평균을 계산하고 이 object 에 적용하기 위해 위의 함수들을 call 하기만 하면 됩니다.

-- if there is more than one tracking dot, calculate the rotation and scaling
if (#rect.dots > 1) then
-- calculate the average rotation of the tracking dots
rotate = calcAverageRotation( rect.dots )
-- calculate the average scaling of the tracking dots
scale = calcAverageScaling( rect.dots )
-- apply rotation to rect
rect.rotation = rect.rotation + rotate
-- apply scaling to rect
rect.xScale, rect.yScale = rect.xScale * scale, rect.yScale * scale
end

main.lua

sample9.lua


반응형