플렉스에서 각종 이펙트를 사용하다가 보니 안되는게 몇가지 있었는데.. 내 기억에 남는것은 확대하면서 회전하는 효과를 주려고 했을때다.
영화에서 보면 중요한 신문기사 같은거 빙빙 돌면서 확대대서 중앙에 턱~~ 나오는 바로 그런 효과를 주고 싶었었다.
이미지에 Parallel 을 이용하여 Zoom 과 Rotate 를 붙여서 사용하려고 했었다. ( 이걸 해보신분은 지금쯤 감 잡으셨을 겁니다. )
효과가 적용되는 순간 이미지는 화면밖으로 날아가버린다. 아무리 두번 세번 체크를 해도 사용상 틀린곳이 없다. 그럼에도 화면밖으로 보이지도 않을정도로 멀리 날아간다. 나는 그저 버그려니 생각했었다...
그러던 어느날... 실무 레퍼런스로 여기고 시도 때도 없이 찾아가는 지돌스타님 블로그에서 이유를 알게 되었다. 문제는 tranform.matrix 였다. Zoom과 Rotate 가 같은 matrix를 참조하면서 서로 다른 값을 넘기기 때문이다. 그럼 해결방법이 없을까..?
http://blog.jidolstar.com/202 << 여기 지돌스타님 블로그와 docs의 내용을 참고하시기 바랍니다.
Zoom 은 matrix 의 a,d 를 바꾼다. Rotate 는 a,b,c,d 를 바꾼다. 그러려니 하면서 지돌스타님 예제를 가지고 해보고있었는데...가만 보니 이상하다..? 어도비 독스에 의하면... a,b,c,d는 삼각함수로 회전에 관계하고있고.. a,d는 확대 축소인데...지돌스타님 예제를 이래저래 움직이다 보니 그림이 작아졌다 커졌다 하면서 회전도 하는것이 아닌가. 단순히 a,d 에 값이 들어오면 확대축소고 a,b,c,d 다 들어오면 회전이고 하는식으로 계산하는게 아닌가보다... 뭔가 방법이 있겠다 싶어서 소스를 긁었다. 손으로 정확한 수치를 기입하기 위해서 소스를 개조하고 학창시절 애용하던 공학용 계산기를 꺼내 들었다. 사실 변환행렬이니 하는걸 배운적이 있는지 없는지도 모르겠는 나로서는 저렇게 밖에 생각하지 못했다. 게다가 matrix 라는 클래스를 이래저래 해봐도 잘 안된다. 그리하여...그부분은 나중에 좀 더 공부해 보기로 했다. 일단은 모르면 손발이 고생해야 한다.
지돌스타님 예제를 고쳐서 Slider를 NumericStepper로 바꿨다. 계산기 두드려가면서.. 돌리면 값이 이렇게 되야 하는데 저렇게 되야 하는데..?? 첨엔 Label 을 여러게 놓고 각 속성값을 바인딩해서 변화되는걸 체크하고있었지만...뭔가 의심이 들어서 갱신 버튼도 만들고...하다가 그냥 확 타이머를 돌려 버렸다.
docs 에 하나 이상한게 있는데 tx, ty 값이 픽셀수치만큼 이동이라고 되어있다. 마치 x,y 좌표에서 tx, ty 만큼 이동한다고 말하는듯 하지만...여러번 테스트 해본결과 tx, ty는 x, y 좌표라고 결론지었다.
자 이걸 가지고 놀면서 30도를 돌리면 어떻게 되나..docs를 보고 값을 넣어봤다. a,d = 0.866, b=0.5, c=-0.5 30도 돌아간다. 여기서 scaleX,Y를 0.5 를 줬더니..a,b,c,d가 각각 반으로 뚝 떨어진다... 아하~ 이런구조로 되어있구나... 이제 해결방법을 알았다.
자 그림 지금부터 신물나는 수학의 세계로 떠나봅시다~.
나는 이전에 수학의 필요성을 느껴 고등학교 졸업하고 어디로 사라졌는지도 모르겠는 정석을 다시 산적이 있다...
요긴하게 쓰인다. 두껍고 무겁고 딱딱해서 책꽃이 끝에 꽂아두면 책이 밀리지도 않고.. 컵라면 압력용으로도 좋고 냄비 받침으로도 안성맞춤이다.
하지만 오늘은 이걸 펼처서 삼각함수 부분을 봐야 했다. 고등학교때는 당췌 이런 학문이 어디 쓰이는지 도통 알 수가 없었는데...
왜 선생님들은 이런건 안가르쳐 주는지 모르겠다. 알았으면 좀 더 열심히 했을지도....ㅠ.ㅠ
Zoom의 경우 간단하게 matrix의 a,b,c,d 값에 곱하기만 하면 된다. 문제는 tx,ty 좌표다. 이게 안맞으니 얘가 화면밖으로 마구 날아가고 하는것이리라...tx,ty를 구하기 위해 이걸 도식화 해보면 다음과 같다... 위의 예제를 적용하였다. 위 예제에서 이미지의 크기는 300 x 200 이고 이미지가 있는 Canvas는 640 x 480 이다. 종이와 연필과 계산기를 꺼내들고 계산을 해보기 시작했다. 사실 이렇게 정리하기 까지 한참이 걸렸다.
보기 좋게 뒤집으니 y축이 위로가는게 이제 좀 수학시간에 보던거랑 비슷하다.
점 O는 회전,확대,축소의 중심이고 점P는 변경전의 x,y 좌표이다. 점Q는 움직여야할 x,y 좌표로서 우리가 구해야할 것이 바로 점 Q가 되겠다.
그럼 풀어보자...
점 O를 원점(0,0) 이라고 보면...
점 P는 Px = RcosΘ, Py = RsinΘ 가 된다. <-----①
Θ 는 점O가 원점일때 점 P가 x축과 이루는 각도다.
그럼 이 점 P를 Φ 만큼 이동시켰을때를 점 Q 라하면..
Qx = Rcos(Θ + Φ) , Qy = Rsin(Θ + Φ) 가 된다.
가 된다. 이걸 합차공식인지 덧셈정린지...해서 보면..
Qx = RcosΘcosΦ - RsinΘsinΦ
Qy = RsinΘcosΦ + RcosΘsinΦ 이 되고... ① 번식을 대입하면..
Qx = Px cosΦ - Py sinΦ
Qy = Py cosΦ + Px sinΦ
이식은 원점을 중심으로 하니..이걸 점 O(Ox, Oy) 의 위치로 이동시킨후 점 Q에대해 정리하면..
Qx = (Px - Ox) cosΦ - (Py - Oy) sinΦ + Ox <-------②
Qy = (Py - Oy) cosΦ + (Px - Ox) sinΦ + Oy 이렇게 나온다.
이것은 점O 를 중심으로 회전하는 점 Q 에 대한 공식이다. 회전만 시키려면 이공식을 그대로 사용하면 된다. 사실 이 결과 자체는 인터넷에서도 쉽게 찾을 수 있었지만...여기서 확대 축소를 주려고 하니 이게 뭔소린지를 몰라서 바꿀수가 없었다...그래서 결국 이렇게 유도해 내기까지 왔다. 우리는 이제 이게 어떻게 이루어 진것인지 알았으니 여기 확대 축소를 넣어볼것이다.
줌의 변화에 영향을 받는 좌표들에 t 를 붙여서 ② 식을 다시 써 보자. 지금까지 구한 회전공식은 이미지의 크기가 300 x 200 이라고 가정하고 계산한 것이다. 이 이미지가 점 O를 중심으로 반으로 작아졌다고 한다면 바뀌게 될 좌표들을 생각해 보라.
Qxt = (Pxt - Ox) cosΦ - (Pyt - Oy) sinΦ + Ox <-------③
Qyt = (Pyt - Oy) cosΦ + (Pxt - Ox) sinΦ + Oy
점 Pt (Pxt, Pyt)는 Δ(줌의 변화율) 에 의해 원점과 점 P(Px, Py) 사이에 위치하게 된다. Δ 는 확대 축소의 비율이므로 Δ 가 0 일때 점 Pt 는 점 O 에 있게되고 Δ가 1 일때 점 Pt 는 점 P 에 있게된다. 이제 이것을 가지고 점 Pt 에 대해 직선의 방정식을 세워보면... 다행히 내가산 정석에는 직선의 방정식이 있다.
Pxt = - (Ox - Px)*Δ + Ox
Pyt = - (Oy - Py)*Δ + Oy
이러한 식을 세울수 있다. 그럼 이식을 ③ 식에 대입해 보자.
Qxt = - (Ox - Px) * Δ * cosΦ + (Oy - Py) * Δ * sinΦ + Ox
Qyt = - (Oy - Py) * Δ * cosΦ - (Ox - Px) * Δ * sinΦ + Oy
드디어 우리가 필요로하는 점 Q를 구해냈다. 사실 나는 계산 잘못해서 몇번 이나 다시했다...
자 그럼 이제 이것을 프로그램으로 옮겨보자. Flex에서 각도는 radian 임을 명심하자 친절하게 degree로 바꾸는법도 있으니 실수하지 말자.
matrix.tx = -(Ox - Xo) * Delta * Math.cos(Phi * Math.PI / 180) + (Oy - Yo) * Delta * Math.sin(Phi * Math.PI / 180) + Ox;
matrix.ty = -(Oy - Yo) * Delta * Math.cos(Phi * Math.PI / 180) - (Ox - Xo) * Delta * Math.sin(Phi * Math.PI / 180) + Oy;
이것으로 회전과 줌을 동시에 적용할 때 필요한 위치좌표 tx, ty를 얻었다. 남은 a,b,c,d 의 값은 docs 의 회전 부분에 나와있는데로 a,b,c,d 에 각각 cosΦ , sinΦ, -sinΦ, cosΦ 을 넣되 얘네들한테 각각 줌 변화율 Δ를 곱해주기만 하면 되겠다. 나머지 잡다구리 한 것들은 알아서 클래스 화 시키도록 하자. 정석과 오랫만에 씨름을 하고...인터넷에 삼각함수 공식을 찾아가면서도 원하는걸 이루고 나니 기분은 좋다. 이걸 더 간단하게 어떻게 구현 할 수 있을지는 모르겠다. 행렬식으로 표현한 공식도 인터넷에서 몇개 본거같은데... 내가 샀던 정석 10-나 에는 행렬이 없다 ㅠ.ㅠ 다음에 언제 행렬도 공부 좀 해야겠고...화면을 주무르려는 입장에서 역시나 좌표계 놀음을 하려면 삼각함수 공부를 열심히 해야겠다는 생각이 든다...
이런식의 효과를 뭐라고 부르는지 몰라서 영화에서 자주보던...그냥 NewsPaper 라고 이름지었다. 뭐 기본적으로 effect 를 적용하는데 필요한 것들을 대충 다른 effect 들과 비슷하게 구현해 보았다.
matrix 클래스에 보면 concat 이니 rotate, scale 함수들이 많은데 이걸 어떻게 조합해서 쓸 수 있을거 같다는 생각이 들긴합니다. 혹시 아시는분 방법좀 알려주시면 감사하겠습니다. (이런식의 효과 이름도 아시면 좀 알려주세요)
P.S 지돌스타님 충고대로 sin, cos을 테이블로 적용해 보았다. 0.1 도 단위로 0~3599 까지 각각 3600 개의 Array 를 만들어 사용했다.
결과는 놀라웠다... 속도향상과 부드러운 움직임이 눈에 띄게 달라졌다. 역시 고수의 충고는 잘 새겨 들어야 한다.
NewsEffect.mxml
댓글을 달아 주세요
좋은 정보 감사합니다. 멋지게 구현하신 모습 좋습니다.
2010/02/01 14:18 [ ADDR : EDIT/ DEL : REPLY ]속도가 더 빠른 계산을 위해서 cos, sin 값등은 lookup table을 만드셔서 사용하시면 계산이 훨씬 빠를겁니다. ^^
저의 웹 플로피에 첫 방명록을 남겨주시는 분이 지돌스타님이시라니 가문의 영광입니다. 그렇군요...테이블을 쓰는게 더 빠르군요. 언제 한번 또 고쳐봐야겠습니다. ^^
2010/02/02 14:50 [ ADDR : EDIT/ DEL ]왔다감.. ^^ 정리 잘 해 놨네..
2010/02/01 16:04 [ ADDR : EDIT/ DEL : REPLY ]