회전하는 입방체 면 위에 비디오 재생하기
이 예제는 회전하는 입방체의 면 위에 비디오를 보여주기 위한 JavaFX 기술의 사용방법을 보여 준다. 예제는 사용자가 비디오를 재생하려 입방체의 면을 클릭하거나, 입방체를 회전하기 위해 면을 드래그 하는 것을 가능하게 한다.
코드 이해하기
VideoCube class는 사용자가 마우스로 회전시키거나 큐브 면에서 비디오를 재생 할 수 있는 3-D 큐브를 생성한다.
Point class는 그림 1과 같다. 이것은 3-D 공간내의 점을 나타내고 좌표 기반에서 회전 기능을 제공한다.
class Point {
var x: Number;
var y: Number;
var z: Number;
function rotateX(cos, sin) {
var tmp = cos * y - sin * z;
z = cos * z + sin * y;
y = tmp;
}
function rotateY(cos, sin) {
var tmp = cos * x + sin * z;
z = cos * z - sin * x;
x = tmp;
}
function rotateZ(cos, sin) {
var tmp = cos * x - sin * y;
y = cos * y + sin * x;
x = tmp;
}
}
그림 1: 3D를 지원하는 Point class
그림 2처럼 입방체의 지점들이 선언된다. 마지막 4개의 점은 자동적으로 계산됨을 주의하라.
def ful = Point { x:-r y:-r z: r }
def fur = Point { x: r y:-r z: r }
def flr = Point { x: r y: r z: r }
def fll = Point { x:-r y: r z: r }
def bul = Point { x: bind - ful.x y: bind - ful.y z: bind - ful.z }
def bur = Point { x: bind - fur.x y: bind - fur.y z: bind - fur.z }
def blr = Point { x: bind - flr.x y: bind - flr.y z: bind - flr.z }
def bll = Point { x: bind - fll.x y: bind - fll.y z: bind - fll.z }
그림 2: 입방체 점들의 초기화
회전 애니메이션은 그림 3과 같다. 초당 25 프레임으로 보여지기 위해 40ms 마다 좌표를 다시 계산한다. ax 와 ay 변수들은 적당한 x 와 y 축 위에 입방체가 결정되는 각을 정의한다. 첫번째 4개의 점들만 변경된 것을 확인하라.
var ax = 0.002; def cx = bind Math.cos(ax); def sx = bind Math.sin(ax); var ay = -0.006; def cy = bind Math.cos(ay); def sy = bind Math.sin(ay); def rotation = Timeline { repeatCount: Timeline.INDEFINITE keyFrames: KeyFrame { time: 40ms action: function() { if (ax != 0) { ful.rotateX(cx, sx); fur.rotateX(cx, sx); flr.rotateX(cx, sx); fll.rotateX(cx, sx); } if (ay != 0) { ful.rotateY(cy, sy); fur.rotateY(cy, sy); flr.rotateY(cy, sy); fll.rotateY(cy, sy); } } } } rotation.play()
그림 3: 초당 25번 재연산 발생
PerspectiveTransform class는 마우스 좌표의 변환을 지원을 수행하지 않는 효과이다. 시점 변경기반의 폴리곤은 그림 4와같이, 제어 함수를 제공한다. 마우스 버튼 클릭시에는, 대화 상자가 열리는 것이 보인다. 마우스 드래그시에는, 회전각이 변경된다.
Polygon {
points: bind [
pt.ulx, pt.uly,
pt.urx, pt.ury,
pt.lrx, pt.lry,
pt.llx, pt.lly
]
cursor: Cursor.HAND
blocksMouse: true
onMouseClicked: function (event) {
rotation.pause();
if (JFileChooser.APPROVE_OPTION == chooser.showOpenDialog(null)) {
source = chooser.getSelectedFile().toURI().toString()
}
rotation.play();
}
onMouseDragged: function(event) {
ax = if (-5 < event.dragY and event.dragY < 5) then 0 else - event.dragY / 10000;
ay = if (-5 < event.dragX and event.dragX < 5) then 0 else event.dragX / 10000;
}
}
그림 4: Mouse Events 지원
비디오가 안 열린다면, 그림 5에서와 같이 간단한 애니메이션이 선언된다. 이 노드들의 집단은 시점 변경을 사용함으로 변형된다.
Group {
effect: pt
visible: bind error
content: [
Rectangle {
x: -100 width: 200
y: -100 height: 200
fill: bind background
stroke: bind foreground
strokeWidth: 2
}
Circle { radius: 85 fill: bind foreground }
Circle { radius: 80 fill: Color.web("#c7b668") }
Circle { radius: 70 fill: Color.web("#645f37") }
Circle { radius: 65 fill: bind background }
Text {
x: -34
y: 40
content: bind "{number}"
fill: bind foreground
font: Font { size: 120 embolden: true }
}
Line { startX: -80 endX: 80 stroke: bind foreground strokeWidth: 2 }
Line { startY: -80 endY: 80 stroke: bind foreground strokeWidth: 2 }
Arc {
radiusX: 80
radiusY: 80
startAngle: bind start
length: bind length
type: ArcType.ROUND
opacity: 0.2
}
]
}
그림 5: 입방체 표면에서의 애니메이션
비디오가 열린다면, 그림 6처럼 media view가 재생된다. 이 노드는 시점 변경을 사용함으로 변형된다. 부피는 면의 위치에 종속됨을 주의하라.
MediaView {
effect: pt
visible: bind not error
mediaPlayer: MediaPlayer {
media: bind media
autoPlay: true
repeatCount: MediaPlayer.REPEAT_FOREVER
volume: bind if (z > 0)
then 0.25 * z / r
else 0
}
}
그림 6: 변형된 비디오의 재생
코드 변형
scene은 그림 7처럼 생성된다. 각각의 면마다 사용된 점들의 순서를 변경해 줄 수 있다. 점들의 순서 변경은 면위의 비디오를 회전하거나 거울처럼 반사하는 것이 가능해진다. source 속성은 예제가 시작될 때 자동적으로 읽어질 비디오를 알려준다.
scene: Scene {
content: [
Face { number: 1 ul: ful ur: fur lr: flr ll: fll source: "{__DIR__}VideoCube.avi" }
Face { number: 2 ul: flr ur: fur lr: bll ll: bul }
Face { number: 3 ul: bur ur: fll lr: flr ll: bul }
Face { number: 4 ul: bll ur: fur lr: ful ll: blr }
Face { number: 5 ul: bur ur: blr lr: ful ll: fll }
Face { number: 6 ul: bur ur: bul lr: bll ll: blr }
]
}
그림 7: Scene 생성
Sergey MalenkovSoftware Engineer,
Sun Microsystems