﻿{"id":1832,"date":"2014-12-11T01:41:50","date_gmt":"2014-12-10T16:41:50","guid":{"rendered":"http:\/\/yucchi.jp\/blog\/?p=1832"},"modified":"2014-12-11T01:55:04","modified_gmt":"2014-12-10T16:55:04","slug":"javafx-%e3%81%ae%e6%a8%99%e6%ba%96%e6%a9%9f%e8%83%bd%e3%81%a0%e3%81%91%e3%81%a7%e3%82%b7%e3%83%b3%e3%83%97%e3%83%ab%e3%81%aa-3d-%e3%83%88%e3%82%a4%e3%83%94%e3%82%a2%e3%83%8e%e3%82%92%e3%81%a4%e3%81%8f","status":"publish","type":"post","link":"http:\/\/yucchi.jp\/blog\/?p=1832","title":{"rendered":"JavaFX \u306e\u6a19\u6e96\u6a5f\u80fd\u3060\u3051\u3067\u30b7\u30f3\u30d7\u30eb\u306a 3D \u30c8\u30a4\u30d4\u30a2\u30ce\u3092\u3064\u304f\u308d\u3046"},"content":{"rendered":"<p>\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u306f\u3001<a href=\"http:\/\/www.adventar.org\/calendars\/380\" target=\"_blank\">JavaFX Advent Calendar 2014<\/a>, 11\u65e5\u76ee\u3067\u3059\u3002<\/p>\n<p>\u6628\u65e5\u306f @toruwest \u3055\u3093\u306e\u300c<a href=\"http:\/\/toruwest.hatenablog.com\/entry\/2014\/12\/10\/110731\" target=\"_blank\">JavaFX\u306eTreeView\u3067\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u3057\u3066\u307f\u308b<\/a>\u300d\u3067\u3057\u305f\u3002<\/p>\n<p>\u660e\u65e5\u306f @skrb \u3055\u3093\u306e\u300cJava Advent Calendar\u3068\u4e00\u7dd2\u306b\u306a\u306b\u304b\u66f8\u304d\u307e\u3059\u300d\u3067\u3059\u3002<\/p>\n<p>\u4eca\u5e74\u3082\u6b8b\u308a\u5c11\u306a\u304f\u306a\u3063\u3066\u304d\u3066\u3044\u308d\u3044\u308d\u3068\u5fd9\u3057\u304f\u306a\u3063\u3066\u304d\u307e\u3057\u305f\u3002<\/p>\n<p>\u305d\u3093\u306a\u4eca\u65e5\u3053\u306e\u9803\u3001\u4f55\u6545\u304b\u300c\u732b\u3075\u3093\u3058\u3083\u305f\u300d\u306e\u30e1\u30ed\u30c7\u30a3\u304c\u30de\u30a4\u30d6\u30fc\u30e0\u3068\u306a\u3063\u3066\u304d\u307e\u3057\u305f\u3002<\/p>\n<p>\u5fd9\u3057\u3044\u306e\u306a\u3089\u732b\u306e\u624b\u3082\u501f\u308a\u305f\u3044\u72b6\u6cc1\u306a\u306e\u306b\u8e0f\u3093\u3058\u3083\u3063\u305f\u3089\u3044\u3051\u306a\u3044\u306e\u306b\u306d\uff01<\/p>\n<p>\u3068\u8a00\u3046\u308f\u3051\u3067\u300c\u732b\u3075\u3093\u3058\u3083\u3063\u305f\u300d\u3092\u5f3e\u304d\u305f\u304f\u306a\u3063\u3066 JavaFX \u3067 ToyPiano \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u4f5c\u308b\u3053\u3068\u306b\u3057\u307e\u3057\u305f\u3002<\/p>\n<p>JavaFX \u306e\u30b5\u30f3\u30d7\u30eb\u306b\u3000Xylophone \u3068\u3044\u3046 3D \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>\u305d\u308c\u3092\u53c2\u8003\u306b JavaFX 8 \u306e\u6a19\u6e96\u6a5f\u80fd\u3060\u3051\u3092\u4f7f\u3063\u3066\u4f5c\u3063\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>\u4eca\u56de\u4f5c\u308b\u306e\u306f\u30c8\u30a4\u30d4\u30a2\u30ce\u306a\u306e\u3067\u548c\u97f3\u306b\u3082\u5bfe\u5fdc\u3055\u305b\u308b\u305f\u3081\u306b\u30bf\u30c3\u30c1\u30a4\u30f3\u30bf\u30d5\u30a7\u30fc\u30b9\u3092\u5229\u7528\u3057\u307e\u3059\u3002<\/p>\n<p>\u3088\u3063\u3066\u52d5\u4f5c\u53ef\u80fd\u306a\u306e\u306f\u30bf\u30c3\u30c1\u30d1\u30cd\u30eb\u5bfe\u5fdc\u306e OS \u9650\u5b9a\u3068\u306a\u3063\u3066\u3057\u307e\u3044\u307e\u3059\u3002<\/p>\n<p>\u3082\u3061\u308d\u3093\u3001\u30bf\u30c3\u30c1\u30d1\u30cd\u30eb\u306f\u5fc5\u9808\u3067\u3059\u3002(^^;<\/p>\n<p>\u305b\u3063\u304b\u304f 3D \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306b\u3059\u308b\u306e\u3060\u304b\u3089\u9375\u76e4\u3082\u305d\u308c\u306a\u308a\u306b\u52d5\u304b\u3057\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>\u5168\u3066\u3092\u66f8\u3053\u3046\u3068\u3059\u308b\u3068\u51c4\u304f\u9577\u304f\u306a\u3063\u3066\u3057\u307e\u3044\u307e\u3059\u306e\u3067 JavaFX 3D API \u3060\u3051\u3092\u53d6\u308a\u4e0a\u3052\u307e\u3059\u3002<\/p>\n<p>\u30bf\u30c3\u30c1\u30a4\u30f3\u30bf\u30d5\u30a7\u30fc\u30b9\u3084\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u30bf\u30a4\u30de\u30fc\u306e\u4f7f\u7528\u306b\u3064\u3044\u3066\u306f\u5272\u611b\u3055\u305b\u3066\u3044\u305f\u3060\u304d\u307e\u3059\u3002<\/p>\n<p>\u3068\u8a00\u3063\u3066\u3082\u4ed6\u306e\u90e8\u5206\u306f\u7279\u306b\u96e3\u3057\u3044\u3053\u3068\u306f\u3057\u3066\u306a\u3044\u306e\u3067\uff01<\/p>\n<p>\u5b8c\u6210\u7248\u306f\u6b21\u306e\u52d5\u753b\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><iframe loading=\"lazy\" height=\"360\" src=\"\/\/www.youtube.com\/embed\/I-eHAGFtyPI?rel=0\" frameborder=\"0\" width=\"640\" allowfullscreen><\/iframe> <\/p>\n<p>&nbsp;<\/p>\n<p>\u305d\u308c\u3067\u306f\u3001\u3055\u3089\u3063\u3068 JavaFX 3D API \u306b\u3064\u3044\u3066\u8abf\u3079\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>2D \u3068 3D \u306e\u9055\u3044\u306f\u4f55\u304b\uff1f<\/p>\n<p>\u304a\u304a\u3056\u3063\u3071\u306b\u8a00\u3046\u3068 2D \u306e\u5ea7\u6a19\u306b Z \u8ef8\u304c\u8ffd\u52a0\u3055\u308c\u3001\u30e9\u30a4\u30c8\u3084\u30ab\u30e1\u30e9\u3092\u610f\u8b58\u3057\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u304f\u306a\u3063\u305f\u3002<\/p>\n<p>\u305d\u306e\u4ee3\u308f\u308a\u306b\u8868\u73fe\u529b\u304c\u8c4a\u306b\u306a\u3063\u305f\u3002<\/p>\n<p>\u672c\u5f53\u306b\u304a\u304a\u3056\u3063\u3071\u3067\u3059\u304c\u305d\u3093\u306a\u3082\u3093\u3067\u3059\u3002<\/p>\n<p>\u3067\u306f\u3001JavaFX \u3067\u306f\u3058\u3081\u304b\u3089\u7528\u610f\u3055\u308c\u3066\u3044\u308b 3D \u30aa\u30d6\u30b8\u30a7\u30af\u30c8(Primitive Shapes)\u3092\u8868\u793a\u3055\u305b\u308b\u30b7\u30f3\u30d7\u30eb\u306a\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u898b\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p><pre title=\"JavaFX3D_1.java\">\r\npackage jp.yucchi.javafx3d_1;\r\n\r\nimport javafx.application.Application;\r\nimport javafx.scene.Group;\r\nimport javafx.scene.PerspectiveCamera;\r\nimport javafx.scene.Scene;\r\nimport javafx.scene.paint.Color;\r\nimport javafx.scene.shape.Box;\r\nimport javafx.scene.shape.Cylinder;\r\nimport javafx.scene.shape.Sphere;\r\nimport javafx.stage.Stage;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic class JavaFX3D_1 extends Application {\r\n    \r\n    @Override\r\n    public void start(Stage primaryStage) {\r\n        \r\n        final Group root = new Group();\r\n        \r\n        final Box box = new Box(100.0d, 100.0d, 100.0d);\r\n        \r\n        final Cylinder cylinder = new Cylinder(50.0d, 100.0d);\r\n        \r\n        final Sphere sphere = new Sphere(50.0d);\r\n        \r\n        \/\/ box \u3092\u5de6\u3078 (-200) \u79fb\u52d5 (X \u8ef8)\r\n        box.setTranslateX(-200.0d);\r\n        \r\n        \/\/ cylinder \u3092\u53f3\u3078 (200) \u79fb\u52d5 (X \u8ef8) \u305d\u3057\u3066\u4e0a\u3078 (-100) \u79fb\u52d5 (Y \u8ef8)\r\n        cylinder.setTranslateX(200.0d);\r\n        cylinder.setTranslateY(-100.0d);\r\n        \r\n        \/\/ \u900f\u8996\u6295\u5f71\u30ab\u30e1\u30e9\r\n        final PerspectiveCamera cam = new PerspectiveCamera(true);\r\n        \/\/ Field of View \r\n        cam.setFieldOfView(45.5d);\r\n        \/\/ Clipping Planes\r\n        cam.setNearClip(1.0d);\r\n        cam.setFarClip(1_000_000.0d);\r\n        \r\n        \/\/ \u30ab\u30e1\u30e9\u3092 500 \u5f8c\u9000\u3055\u305b\u308b\u3002(Z \u8ef8\u3092 -500)\r\n        cam.setTranslateZ(-500.0d);\r\n\r\n        root.getChildren().addAll(box, cylinder, sphere);\r\n        \r\n        Scene scene = new Scene(root, 640.0d, 360.0d, Color.BLACK);\r\n        \r\n        scene.setCamera(cam);\r\n        \r\n        primaryStage.setTitle(\"JavaFX 3D 1\");\r\n        primaryStage.setScene(scene);\r\n        primaryStage.show();\r\n    }\r\n\r\n    \/**\r\n     * @param args the command line arguments\r\n     *\/\r\n    public static void main(String[] args) {\r\n        launch(args);\r\n    }\r\n    \r\n}\r\n\r\n<\/pre>\n<\/p>\n<p>JavaFX \u3067\u306f\u4e09\u3064\u306e 3D \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304c\u306f\u3058\u3081\u304b\u3089 javafx.scene.shape \u30d1\u30c3\u30b1\u30fc\u30b8\u306b\u5b9a\u7fa9\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>Box<\/p>\n<p>Cylinder<\/p>\n<p>Sphere<\/p>\n<p>\u4e0a\u8a18\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u306f\u305d\u308c\u3089\u3092\u4e0b\u56f3\u306e\u3088\u3046\u306b\u8868\u793a\u3055\u305b\u3066\u3044\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/11.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"1\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"1\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/1_thumb1.png\" width=\"644\" height=\"392\"><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>\u3053\u308c\u3089\u4ee5\u5916\u306f\u81ea\u5206\u3067 TriangleMesh \/ MeshView \u3092\u99c6\u4f7f\u3057\u3066 3D \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u4f5c\u308a\u4e0a\u3052\u308b\u304b\u3001\u30e2\u30c7\u30eb\u30a4\u30f3\u30dd\u30fc\u30bf\u30fc\u3092\u4f7f\u7528\u3059\u308b\u304b\u3057\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u3044\u3067\u3057\u3087\u3046\u3002<\/p>\n<p>\u3055\u3066\u3001\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u306f\u3069\u306e\u3088\u3046\u306b\u7406\u89e3\u3059\u308c\u3070\u3044\u3044\u306e\u3067\u3057\u3087\u3046\u304b\uff1f<\/p>\n<p>\u9806\u756a\u306b\u307f\u3066\u3044\u304d\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp; <font color=\"#666666\">final Box box = new Box(100.0d, 100.0d, 100.0d);<\/font><\/p>\n<p>\u3053\u308c\u306f\u3001\u8fba\u306e\u9577\u3055\u304c\u6a2a\u3001\u7e26\u3001\u5965\u884c\u304d\u305d\u308c\u305e\u308c 100 \u306e\u9577\u3055\u306e\u7acb\u65b9\u4f53\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u4f5c\u3063\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp; <font color=\"#666666\">final Cylinder cylinder = new Cylinder(50.0d, 100.0d);<\/font><\/p>\n<p>\u3053\u3061\u3089\u306f\u3001\u534a\u5f84 50\u3001\u9ad8\u3055 100 \u306e\u30b7\u30ea\u30f3\u30c0\u30fc\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u4f5c\u3063\u3066\u307e\u3059\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp; <font color=\"#666666\">final Sphere sphere = new Sphere(50.0d);<\/font><\/p>\n<p>\u6700\u5f8c\u306b\u534a\u5f84 50 \u306e\u7403\u4f53\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u4f5c\u3063\u3066\u307e\u3059\u3002<\/p>\n<p>\u306f\u3058\u3081\u304b\u3089\u5b9a\u7fa9\u3055\u308c\u3066\u3044\u308b\u306e\u3067\u304a\u624b\u8efd\u306b\u4f5c\u308c\u307e\u3059\u3002<\/p>\n<p>\u3053\u308c\u3089 3D \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u3053\u306e\u307e\u307e\u3067\u306f\u5168\u3066\u5ea7\u6a19\u539f\u70b9\u3092\u4e2d\u5fc3\u306b\u914d\u7f6e\u3055\u308c\u91cd\u306a\u3063\u3066\u3057\u307e\u3044\u307e\u3059\u3002<\/p>\n<p>\u306a\u306e\u3067\u6b21\u306e\u3088\u3046\u306b\u79fb\u52d5\u3055\u305b\u3066\u3044\u307e\u3059\u3002<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp; \/\/ box \u3092\u5de6\u3078 (-200) \u79fb\u52d5 (X \u8ef8)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; box.setTranslateX(-200.0d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ cylinder \u3092\u53f3\u3078 (200) \u79fb\u52d5 (X \u8ef8) \u305d\u3057\u3066\u4e0a\u3078 (-100) \u79fb\u52d5 (Y \u8ef8)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cylinder.setTranslateX(200.0d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cylinder.setTranslateY(-100.0d);<\/font><\/p>\n<p>javafx.scene.Node \u30af\u30e9\u30b9\u306e setTranslateX(double value), setTranslateY(double value), setTranslateZ(double value) \u3068\u8a00\u3046\u4fbf\u5229\u306a\u79fb\u52d5\u30e1\u30bd\u30c3\u30c9\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>\u305d\u308c\u305e\u308c X \u8ef8\u3001Y \u8ef8\u3001Z \u8ef8\u65b9\u5411\u3078\u79fb\u52d5\u3067\u304d\u307e\u3059\u3002<\/p>\n<p>\u3053\u3053\u3067\u6ce8\u610f\u304c\u5fc5\u8981\u306a\u306e\u306f Y \u8ef8 \u3067\u3059\u3002<\/p>\n<p>\u6700\u521d\u306b\u3082\u8aac\u660e\u3057\u305f\u3088\u3046\u306b JavaFX \u306e 3D \u5ea7\u6a19\u306f 2D \u306e\u3082\u306e\u306b Z \u8ef8\u304c\u52a0\u3048\u3089\u308c\u305f\u3082\u306e\u306a\u306e\u3067\u4e0a\u65b9\u5411\u306b\u79fb\u52d5\u3055\u305b\u308b\u5834\u5408\u306f\u3001<\/p>\n<p>setTranslateY(double value) \u306e\u5f15\u6570\u306e\u5024\u306f\u8ca0\u306e\u5024\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>\u6b21\u306f\u30ab\u30e1\u30e9\u306b\u3064\u3044\u3066\u898b\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>\u30ab\u30e1\u30e9\u306b\u306f PerspectiveCamera (\u900f\u8996\u6295\u5f71\u30ab\u30e1\u30e9) \u3068 ParallelCamera (\u76f4\u6295\u5f71\u30ab\u30e1\u30e9) \u306e\u4e8c\u7a2e\u985e\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>\u4eca\u56de\u306f PerspectiveCamera \u3092\u4f7f\u7528\u3057\u307e\u3059\u3002<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u900f\u8996\u6295\u5f71\u30ab\u30e1\u30e9<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final PerspectiveCamera cam = new PerspectiveCamera(true);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Field of View <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cam.setFieldOfView(45.5d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Clipping Planes<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cam.setNearClip(1.0d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cam.setFarClip(1_000_000.0d);<\/font><\/p>\n<p>PerspectiveCamera cam = new PerspectiveCamera(true); \u306e\u5f15\u6570\u306f fixedEyeAtZero\u30d7\u30ed\u30d1\u30c6\u30a3\u3067 true \u306b\u8a2d\u5b9a\u3059\u308b\u3053\u3068\u306b\u3088\u3063\u3066<\/p>\n<p>\u30ab\u30e1\u30e9\u306e\u4f4d\u7f6e\u304c\u539f\u70b9\u306b\u914d\u7f6e\u3055\u308c\u307e\u3059\u3002<\/p>\n<p>\u3061\u306a\u307f\u306b\u3053\u306e\u5834\u5408\u306e\u539f\u70b9\u306e\u4f4d\u7f6e\u306f\u753b\u9762\u306e\u3069\u771f\u3093\u4e2d\u3067\u3059\u3002<\/p>\n<p>\u3053\u308c\u3092 true \u306b\u8a2d\u5b9a\u3059\u308b\u3053\u3068\u306b\u3088\u3063\u3066\u5bb9\u6613\u306b\u30ab\u30e1\u30e9\u3092\u52d5\u304b\u3059\u3053\u3068\u304c\u53ef\u80fd\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>\u30ab\u30e1\u30e9\u3092\u539f\u70b9\u4f4d\u7f6e\u306b\u751f\u6210\u3059\u308b\u3053\u3068\u306f\u4e0a\u8a18\u306e\u3088\u3046\u306b\u7c21\u5358\u306b\u3067\u304d\u307e\u3059\u3002<\/p>\n<p>\u6b21\u306b\u30ab\u30e1\u30e9\u306e\u5199\u308a\u5177\u5408\u3092\u8a2d\u5b9a\u3057\u307e\u3059\u3002<\/p>\n<p>\u8996\u91ce\u89d2\u306e\u8a2d\u5b9a\u306f\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u3057\u307e\u3059\u3002<\/p>\n<p>&nbsp;&nbsp; <font color=\"#666666\">cam.setFieldOfView(45.5d);<\/font><\/p>\n<p>\u5f15\u6570\u306e\u5024\u3001\u8996\u91ce\u89d2 45.5 \u5ea6\u3067\u8a2d\u5b9a\u3057\u307e\u3057\u305f\u3002\u4f55\u51e6\u304b\u3067 OpenGL \u306e\u8a18\u4e8b\u304b\u4f55\u304b\u3067\u3053\u308c\u304f\u3089\u3044\u304c\u826f\u3044\u3068\u898b\u305f\u3088\u3046\u306a\u8a18\u61b6\u304c\u3042\u308b\u306e\u3067(^^;<\/p>\n<p>\u6b21\u306b\u30ab\u30e1\u30e9\u304b\u3089\u3069\u308c\u304f\u3089\u3044\u306e\u8ddd\u96e2\u3092\u5199\u3059\u306e\u304b\u8a2d\u5b9a\u3057\u307e\u3059\u3002<\/p>\n<p>\u30ab\u30e1\u30e9\u304b\u3089\u3053\u308c\u3060\u3051\u96e2\u308c\u3066\u3044\u308c\u3070\u5199\u3059\u3088\u3063\u3066\u306e\u304c<\/p>\n<p>&nbsp;&nbsp;&nbsp; <font color=\"#666666\">cam.setNearClip(1.0d);<\/font><\/p>\n<p>\u3067\u3001\u5f15\u6570\u306e\u5024 1.0 \u3067\u8a2d\u5b9a\u3055\u308c\u3066\u307e\u3059\u3002\u3053\u308c\u4ee5\u4e0a\u8fd1\u3044\u7269\u306f\u5199\u308a\u307e\u305b\u3093\u3002<\/p>\n<p>\u30ab\u30e1\u30e9\u304b\u3089\u3069\u308c\u3060\u3051\u96e2\u308c\u3066\u3044\u308b\u3068\u3053\u308d\u307e\u3067\u5199\u3059\u304b\u306f<\/p>\n<p>&nbsp;&nbsp;&nbsp; <font color=\"#666666\">cam.setFarClip(1_000_000.0d);<\/font><\/p>\n<p>\u5f15\u6570\u306e\u5024\u30011_000_000 \u307e\u3067\u5199\u308a\u307e\u3059\u3002<\/p>\n<p>\u3053\u308c\u4ee5\u4e0a\u9060\u304f\u306f\u5199\u308a\u307e\u305b\u3093\u3002<\/p>\n<p>\u3053\u308c\u3089\u8a2d\u5b9a\u306f\u30b1\u30fc\u30b9\u30d0\u30a4\u30b1\u30fc\u30b9\u304b\u304a\u597d\u307f\u3067\uff01<\/p>\n<p>\u30ab\u30e1\u30e9\u3092\u914d\u7f6e\u3001\u8a2d\u5b9a\u3057\u305f\u306e\u306f\u3044\u3044\u3051\u3069\u3053\u308c\u3067\u306f\u539f\u70b9\u914d\u7f6e\u306a\u306e\u3067 sphere \u306e\u3069\u771f\u3093\u4e2d\u306a\u306e\u3067\u6b8b\u5ff5\u306a\u72b6\u614b\u3067\u3059\u3002<\/p>\n<p>\u305d\u3053\u3067\u30ab\u30e1\u30e9\u3092\u79fb\u52d5\u3055\u305b\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>Z \u8ef8\u624b\u524d\u65b9\u5411\u306b\u30ab\u30e1\u30e9\u3092\u79fb\u52d5\u3055\u305b\u307e\u3059\u3002<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30ab\u30e1\u30e9\u3092 500 \u5f8c\u9000\u3055\u305b\u308b\u3002(Z \u8ef8\u3092 -500)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cam.setTranslateZ(-500.0d);<\/font><\/p>\n<p>\u3053\u308c\u3067\u539f\u70b9\u304b\u3089 500 Z \u8ef8\u65b9\u5411\u306b\u5f8c\u9000\u3057\u305f\u4f4d\u7f6e\u306b\u30ab\u30e1\u30e9\u3092\u914d\u7f6e\u3067\u304d\u307e\u3057\u305f\u3002<\/p>\n<p>\u3042\u3068\u306f\u3053\u306e\u30ab\u30e1\u30e9\u3092 Scene \u306b\u30bb\u30c3\u30c8\u3059\u308c\u3070\u3044\u3044\u3060\u3051\u3067\u3059\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color=\"#666666\">scene.setCamera(cam);<\/font><\/p>\n<p>\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u304b\u3089\u539f\u70b9\u914d\u7f6e\u306e\u72b6\u614b\u3067\u30ab\u30e1\u30e9\u306e\u30ec\u30f3\u30ba\u306f Z \u8ef8\u3001\u6b63\u306e\u65b9\u5411\u306b\u5411\u3044\u3066\u3044\u308b\u3053\u3068\u304c\u78ba\u8a8d\u3067\u304d\u307e\u3057\u305f\u3002<\/p>\n<p>\u3053\u308c\u3067 Primitive Shapes \u306e\u751f\u6210\u3068\u79fb\u52d5\u3001PerspectiveCamera \u306e\u751f\u6210\u3068\u8a2d\u5b9a\u3001\u79fb\u52d5\u3001\u64ae\u5f71\u304c\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u308a\u307e\u3057\u305f\u3002<\/p>\n<p>\u3053\u3053\u3067 ParallelCamera (\u76f4\u6295\u5f71\u30ab\u30e1\u30e9) \u3092\u4f7f\u3046\u3068\u3069\u3046\u306a\u308b\u304b\u8a66\u3057\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>\u5148\u307b\u3069\u306e\u30ab\u30e1\u30e9\u306e\u5b9a\u7fa9\u3068\u30ab\u30e1\u30e9\u306e\u79fb\u52d5\u3092\u6b21\u306e\u3088\u3046\u306b\u5909\u66f4\u3057\u307e\u3059\u3002<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u76f4\u6295\u5f71\u30ab\u30e1\u30e9<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final ParallelCamera cam = new ParallelCamera();<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Field of View \u3042\u308a\u307e\u305b\u3093\uff01<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ cam.setFieldOfView(45.5d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Clipping Planes<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cam.setNearClip(1.0d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cam.setFarClip(1_000_000.0d);<\/font><\/p>\n<p>ParallelCamera (\u76f4\u6295\u5f71\u30ab\u30e1\u30e9)\u306e\u30b3\u30f3\u30b9\u30c8\u30e9\u30af\u30bf\u306b fixedEyeAtZero\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u8a2d\u5b9a\u3059\u308b\u5f15\u6570\u306f\u3042\u308a\u307e\u305b\u3093\u3002<\/p>\n<p>Field of View \u3082\u8a2d\u5b9a\u3067\u304d\u307e\u305b\u3093\u3002<\/p>\n<p>\u76f4\u6295\u5f71\u30ab\u30e1\u30e9\u306e\u6027\u8cea\u4e0a\u5fc5\u8981\u306a\u3044\u306e\u3067\u3057\u3087\u3046\u3002<\/p>\n<p>\u3067\u306f\u3001ParallelCamera (\u76f4\u6295\u5f71\u30ab\u30e1\u30e9)\u3092\u4f7f\u3063\u305f\u5834\u5408\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u304c\u3069\u3046\u306a\u308b\u306e\u304b\u78ba\u8a8d\u3057\u3066\u307f\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/1a.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"1a\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"1a\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/1a_thumb.png\" width=\"644\" height=\"392\"><\/a><\/p>\n<p>Primitive Shapes \u306e Sphere \u306e\u4e2d\u5fc3\u304c\u5de6\u4e0a\u306e\u89d2\u306e\u90e8\u5206( 2D \u306e\u539f\u70b9)\u3068\u306a\u308b\u3088\u3046\u306b\u8868\u793a\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>Sphere \u3068 ParallelCamera \u306e\u4f4d\u7f6e\u60c5\u5831\u3092\u4e0b\u8a18\u30b3\u30fc\u30c9\u3092\u66f8\u304d\u52a0\u3048\u3066\u8abf\u3079\u3066\u307f\u307e\u3059\u3002<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(&#8220;Sphere \u306e\u4f4d\u7f6e\u60c5\u5831 &#8221; + sphere.getBoundsInParent());<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(&#8220;ParallelCamera\u306e\u4f4d\u7f6e\u60c5\u5831 &#8221; + cam.getBoundsInParent());<\/font><\/p>\n<p>\u5b9f\u884c\u7d50\u679c\u3067\u5f97\u3089\u308c\u305f\u5024\u306f\u6b21\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><font color=\"#666666\">Sphere \u306e\u4f4d\u7f6e\u60c5\u5831 BoundingBox [minX:-50.0, minY:-50.0, minZ:-50.0, width:100.0, height:100.0, depth:100.0, maxX:50.0, maxY:50.0, maxZ:50.0]<br \/>ParallelCamera\u306e\u4f4d\u7f6e\u60c5\u5831 BoundingBox [minX:0.0, minY:0.0, minZ:0.0, width:0.0, height:0.0, depth:0.0, maxX:0.0, maxY:0.0, maxZ:0.0]<\/font><\/p>\n<p>3D \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3068\u30ab\u30e1\u30e9\u306e\u5ea7\u6a19\u306e\u539f\u70b9\u306f\u540c\u4e00\u3067\u306f\u306a\u3044\u3053\u3068\u304c\u89e3\u308a\u307e\u3059\u3002<\/p>\n<p>\u30c7\u30d5\u30a9\u30eb\u30c8\u306e 2D \u30ab\u30e1\u30e9\u3063\u3066\u3053\u3068\u3067\u3059\u306d\u3002<\/p>\n<p>Sphere \u3068 Cylinder \u3068 Box \u3092\u79fb\u52d5\u3055\u305b\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color=\"#666666\">sphere.setTranslateX(scene.widthProperty().divide(2).doubleValue());&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphere.setTranslateY(scene.getHeight() \/ 2.0d);<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cylinder.setTranslateX(scene.widthProperty().divide(2).doubleValue() + 200.0d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cylinder.setTranslateY(scene.getHeight() \/ 2.0d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; box.setTranslateX(scene.widthProperty().divide(2).doubleValue() &#8211; 200.0d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; box.setTranslateY(scene.getHeight() \/ 2.0d &#8211; 100.0d);<\/font><\/p>\n<p>\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/1b.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"1b\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"1b\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/1b_thumb.png\" width=\"644\" height=\"394\"><\/a><\/p>\n<p><font color=\"#666666\">Sphere \u306e\u4f4d\u7f6e\u60c5\u5831 BoundingBox [minX:270.0, minY:130.0, minZ:-50.0, width:100.0, height:100.0, depth:100.0, maxX:370.0, maxY:230.0, maxZ:50.0]<br \/>ParallelCamera\u306e\u4f4d\u7f6e\u60c5\u5831 BoundingBox [minX:0.0, minY:0.0, minZ:0.0, width:0.0, height:0.0, depth:0.0, maxX:0.0, maxY:0.0, maxZ:0.0]<\/font><\/p>\n<p>PerspectiveCamera (\u900f\u8996\u6295\u5f71\u30ab\u30e1\u30e9)\u3068\u306f\u9055\u3044\u3059\u3079\u3066\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304c\u4e26\u884c\u306b\u8868\u793a\u3055\u308c\u3066\u307e\u3059\u3002<\/p>\n<p>\u8ddd\u96e2\u611f\u3068\u3044\u3046\u304b\u5965\u884c\u304d\u304c\u5168\u7136\u89e3\u3089\u306a\u3044\u3067\u3059\u306d\u3002<\/p>\n<p>ParallelCamera (\u76f4\u6295\u5f71\u30ab\u30e1\u30e9)\u3082\u8a66\u3057\u305f\u3053\u3068\u3060\u3057\u6b21\u3078\u9032\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>3D \u30aa\u30d6\u30b8\u30a7\u30af\u30c8(Primitive Shapes)\u3092\u8868\u793a\u3055\u305b\u308b\u3053\u3068\u306f\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u3063\u305f\u3051\u3069\u3001<\/p>\n<p>\u3067\u3082\u767d\u9ed2\u306a\u3093\u3066\u3044\u3064\u306e\u6642\u4ee3\u3060\uff1f\u3063\u3066\u3044\u3046\u306e\u306f\u3061\u3087\u3063\u3068\u306d\u30fb\u30fb\u30fb<\/p>\n<p>\u3068\u308a\u3042\u3048\u305a cylinder \u306b\u8272\u3092\u3064\u3051\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>\u5148\u307b\u3069\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3067 Primitive Shapes \u3092\u751f\u6210\u3057\u305f\u3042\u3068\u306b\u4e0b\u8a18\u30b3\u30fc\u30c9\u3092\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30d5\u30a9\u30f3\u30b7\u30a7\u30fc\u30c7\u30a3\u30f3\u30b0\u3092\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final PhongMaterial cylinderMaterial = new PhongMaterial();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u62e1\u6563\u5149\u306b\u3088\u308b\u8272\u306e\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cylinderMaterial.setDiffuseColor(Color.RED);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30b9\u30da\u30ad\u30e5\u30e9\u30ab\u30e9\u30fc\uff08\u53cd\u5c04\u5149\u306e\u8272\uff09\u306e\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cylinderMaterial.setSpecularColor(Color.MAGENTA);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30de\u30c6\u30ea\u30a2\u30eb\u3092\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cylinder.setMaterial(cylinderMaterial);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30c9\u30ed\u30fc\u30e2\u30fc\u30c9\u3092\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cylinder.setDrawMode(DrawMode.FILL);<\/font><\/p>\n<p>\u4e0a\u8a18\u30b3\u30fc\u30c9\u306e\u30b3\u30e1\u30f3\u30c8\u306b\u3042\u308b\u3088\u3046\u306b\u3001\u30d5\u30a9\u30f3\u30de\u30c6\u30ea\u30a2\u30eb\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u751f\u6210\u3057\u3001\u62e1\u6563\u5149\u306b\u3088\u308b\u8272\u306e\u8a2d\u5b9a\u3001\u53cd\u5c04\u5149\u306b\u3088\u308b\u8272\u306e\u8a2d\u5b9a\u3092\u3057\u307e\u3059\u3002<\/p>\n<p>\u305d\u3057\u3066\u305d\u306e\u30de\u30c6\u30ea\u30a2\u30eb\u3092 cylinder \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306b\u8a2d\u5b9a\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>\u30c9\u30ed\u30fc\u30e2\u30fc\u30c9\u3082 LINE \u3068\u304b\u8a2d\u5b9a\u3067\u304d\u307e\u3059\u304c FILL \u3092\u8a2d\u5b9a\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>LINE \u306f\u30ef\u30a4\u30e4\u30fc\u30e2\u30c7\u30eb\u306e\u72b6\u614b\u3067\u3059\u3002<\/p>\n<p>\u4e0a\u8a18\u306e\u3088\u3046\u306b\u30de\u30c6\u30ea\u30a2\u30eb\u306e\u8a2d\u5b9a\u306f javafx.scene.paint.PhongMaterial \u30af\u30e9\u30b9\u306e set\u30c1\u30e7\u30e1\u30c1\u30e7\u30e1() \u30e1\u30bd\u30c3\u30c9\u3067\u8a2d\u5b9a\u3057\u307e\u3059\u3002<\/p>\n<p>\u30c1\u30e7\u30e1\u30c1\u30e7\u30e1\u306f\u4f55\u3092\u8a2d\u5b9a\u3059\u308b\u304b\u89e3\u308b\u3088\u3046\u306b\u8a18\u8ff0\u3055\u308c\u3066\u3044\u307e\u3059\u3002\uff08\u3054\u3081\u3093\u306a\u3055\u3044\u3002\u5909\u306a\u8868\u73fe\u3067\uff09<\/p>\n<p>\u30c9\u30ed\u30fc\u30e2\u30fc\u30c9\u306e\u8a2d\u5b9a\u306f javafx.scene.shape.Shape3D \u30af\u30e9\u30b9\u306e setDrawMode(DrawMode value) \u3067\u3059\u3002<\/p>\n<p>\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/22.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"2\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"2\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/2_thumb2.png\" width=\"644\" height=\"397\"><\/a><\/p>\n<p>\u3061\u3087\u3063\u3068\u3053\u306e\u307e\u307e\u3067\u306f\u8272\u306e\u3064\u3044\u3066\u306a\u3044\u6b8b\u308a\u4e8c\u3064\u304c\u5bc2\u3057\u306e\u3067\u305d\u308c\u3089\u306b\u3082\u8272\u3092\u3064\u3051\u3066\u307f\u307e\u3057\u305f\u3002<\/p>\n<p>\u3053\u3053\u3067 Sphere \u3060\u3051\u30b9\u30da\u30ad\u30e5\u30e9\u30d1\u30ef\u30fc\u3092\u8a2d\u5b9a\u3057\u3066\u307f\u307e\u3057\u305f\u3002<\/p>\n<p>\u30c7\u30d5\u30a9\u30eb\u30c8\u5024\u306f 32.0d \u306a\u306e\u3067\u534a\u5206\u306e 16.0d \u3067\u8a2d\u5b9a\u3057\u307e\u3057\u305f\u3002<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30d5\u30a9\u30f3\u30b7\u30a7\u30fc\u30c7\u30a3\u30f3\u30b0\u3092\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final PhongMaterial boxMaterial = new PhongMaterial();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u62e1\u6563\u5149\u306b\u3088\u308b\u8272\u306e\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boxMaterial.setDiffuseColor(Color.GREEN);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30b9\u30da\u30ad\u30e5\u30e9\u30ab\u30e9\u30fc\uff08\u53cd\u5c04\u5149\u306e\u8272\uff09\u306e\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boxMaterial.setSpecularColor(Color.LIGHTGREEN);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30de\u30c6\u30ea\u30a2\u30eb\u3092\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; box.setMaterial(boxMaterial);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30c9\u30ed\u30fc\u30e2\u30fc\u30c9\u3092\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; box.setDrawMode(DrawMode.FILL);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30d5\u30a9\u30f3\u30b7\u30a7\u30fc\u30c7\u30a3\u30f3\u30b0\u3092\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final PhongMaterial sphereMaterial = new PhongMaterial();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u62e1\u6563\u5149\u306b\u3088\u308b\u8272\u306e\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphereMaterial.setDiffuseColor(Color.BLUE);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30b9\u30da\u30ad\u30e5\u30e9\u30ab\u30e9\u30fc\uff08\u53cd\u5c04\u5149\u306e\u8272\uff09\u306e\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphereMaterial.setSpecularColor(Color.LIGHTCYAN);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30b9\u30da\u30ad\u30e5\u30e9\u30d1\u30ef\u30fc\u3092\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphereMaterial.setSpecularPower(16.0d);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30de\u30c6\u30ea\u30a2\u30eb\u3092\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphere.setMaterial(sphereMaterial);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30c9\u30ed\u30fc\u30e2\u30fc\u30c9\u3092\u8a2d\u5b9a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphere.setDrawMode(DrawMode.FILL);<\/font><\/p>\n<p>\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/31.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"3\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"3\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/3_thumb1.png\" width=\"644\" height=\"395\"><\/a><\/p>\n<p>3D \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306b\u8272\u3082\u4ed8\u3051\u308b\u3053\u3068\u304c\u3067\u304d\u305f\u3057\u6b21\u306f\u30e9\u30a4\u30c8\u3092\u8a2d\u5b9a\u3057\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>\u30e9\u30a4\u30c8\u306f\u30a2\u30f3\u30d3\u30a8\u30f3\u30c8\u30e9\u30a4\u30c8\u3068\u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u306e\u4e8c\u7a2e\u985e\u304c\u7528\u610f\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>\u30a2\u30f3\u30d3\u30a8\u30f3\u30c8\u30e9\u30a4\u30c8\u306f\u74b0\u5883\u5149( \u5149\u6e90\u304b\u3089\u306e\u5149\u304c\u76f4\u63a5\u5f53\u305f\u3063\u3066\u3044\u306a\u3044\u90e8\u5206\u3092\u7167\u3089\u3059\u5149\u3001\u7269\u7406\u7684\u306b\u306f\u5149\u3092\u53d7\u3051\u3066\u3044\u308b\u9762\u304b\u3089\u306e\u6563\u4e71\u5149\u3067\u3042\u308b )\u306e\u3053\u3068\u3067\u3059\u3002<\/p>\n<p>\u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u306f\u70b9\u5149\u6e90\u3067\u3059\u3002\u70b9\u5149\u6e90\u3092\u7f6e\u3044\u305f\u4f4d\u7f6e\u304b\u3089\u5168\u65b9\u5411\u306b\u5149\u308a\u304c\u4f38\u3073\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n<p>\u305d\u306e\u5149\u308a\u306f\u8ddd\u96e2\u304c\u96e2\u308c\u308b\u306b\u3057\u305f\u304c\u3063\u3066\u5f31\u304f\u306a\u3063\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n<p>\u305d\u308c\u3067\u306f\u5148\u307b\u3069\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u306b\u3053\u308c\u3089\u4e8c\u3064\u306e\u30e9\u30a4\u30c8\u3092\u914d\u7f6e\u3057\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30a2\u30f3\u30d3\u30a8\u30f3\u30c8\u30e9\u30a4\u30c8<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AmbientLight ambient = new AmbientLight();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ambient.setColor(Color.rgb(184, 134, 11, 0.5));<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PointLight point = new PointLight();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point.setColor(Color.GHOSTWHITE);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u3092\u79fb\u52d5<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point.setTranslateX(-800.0d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point.setTranslateY(-300.0d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point.setTranslateZ(-800.0d);<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; root.getChildren().addAll(box, cylinder, sphere, ambient, point);<\/font><\/p>\n<p>\u30a2\u30f3\u30d3\u30a8\u30f3\u30c8\u30e9\u30a4\u30c8\u3068\u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u3092\u4e0a\u8a18\u30b3\u30fc\u30c9\u306e\u3088\u3046\u306b javafx.scene.LightBase \u30af\u30e9\u30b9\u306e\u8a2d\u5b9a\u30e1\u30bd\u30c3\u30c9\u3092\u4f7f\u3044\u8a2d\u5b9a\u3057\u307e\u3059\u3002<\/p>\n<p>\u305d\u308c\u305e\u308c\u306e\u8272\u3092\u8a2d\u5b9a\u3057\u3066\u3044\u308b\u3060\u3051\u3067\u7279\u306b\u96e3\u3057\u3044\u3053\u3068\u306f\u3057\u306a\u304f\u3066\u3044\u3044\u3088\u3046\u3067\u3059\u3002<\/p>\n<p>\u305f\u3060\u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u306e\u914d\u7f6e\u304c\u539f\u70b9\u306b\u306a\u3063\u3066\u3057\u307e\u3046\u306e\u3067\u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u3092\u79fb\u52d5\u3055\u305b\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>\u79fb\u52d5\u3055\u305b\u306a\u3044\u3068 Sphere \u306e\u4e2d\u5fc3\u4f4d\u7f6e\u306b\u914d\u7f6e\u3055\u308c\u308b\u306e\u3067 Sphere \u304c\u8868\u793a\u3055\u308c\u306a\u304f\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>\u3053\u308c\u3089\u4e8c\u3064\u306e\u30e9\u30a4\u30c8\u3092\u914d\u7f6e\u3057\u305f\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/41.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"4\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"4\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/4_thumb1.png\" width=\"644\" height=\"394\"><\/a><\/p>\n<p>\u3055\u3066\u3001\u30e9\u30a4\u30c8\u3063\u3066\u4e00\u3064\u3060\u3051\u3057\u304b\u914d\u7f6e\u3067\u304d\u306a\u3044\u306e\u3067\u3057\u3087\u3046\u304b\uff1f<\/p>\n<p>\u3061\u3087\u3063\u3068\u8a66\u3057\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8 2<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PointLight point_2 = new PointLight();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point_2.setColor(Color.YELLOW);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8 2 \u3092\u79fb\u52d5<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point_2.setTranslateX(800.0d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point_2.setTranslateY(-300.0d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point_2.setTranslateZ(-800.0d);<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; root.getChildren().addAll(box, cylinder, sphere, ambient, point, point_2);<\/font><\/p>\n<p>\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3057\u305f\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/51.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"5\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"5\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/5_thumb1.png\" width=\"644\" height=\"395\"><\/a><\/p>\n<p>\u8907\u6570\u306e\u30e9\u30a4\u30c8\u304c\u914d\u7f6e\u3067\u304d\u308b\u3088\u3046\u3067\u3059\u3002<\/p>\n<p>\u3067\u3082\u3001\u7279\u5b9a\u306e 3D \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306b\u3060\u3051\u30e9\u30a4\u30c8\u3092\u5f53\u3066\u308b\u306b\u306f\u3069\u3046\u3059\u308c\u3070\u3044\u3044\u306e\u3067\u3057\u3087\u3046\u304b\uff1f<\/p>\n<p>\u3053\u308c\u3082\u7c21\u5358\u306b\u8a2d\u5b9a\u3067\u304d\u307e\u3059\u3002<\/p>\n<p>\u305d\u308c\u3067\u306f\u5148\u307b\u3069\u8ffd\u52a0\u3057\u305f\u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8 2 \u3092 Sphere \u3060\u3051\u306b\u5f53\u3066\u308b\u3088\u3046\u306b\u3057\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>\u4e0b\u8a18\u30b3\u30fc\u30c9\u306e\u3088\u3046\u306b\u30b9\u30b3\u30fc\u30d7\u3092\u8a2d\u5b9a\u3059\u308b\u3060\u3051\u3067\u3059\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color=\"#666666\">point.getScope().add(sphere);<\/font><\/p>\n<p>\u305d\u308c\u3067\u306f\u78ba\u8a8d\u306e\u305f\u3081\u306b\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u5b9f\u884c\u3057\u3066\u307f\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/6.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"6\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"6\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/6_thumb.png\" width=\"644\" height=\"394\"><\/a><\/p>\n<p>\u671f\u5f85\u901a\u308a\u306b Sphere \u3060\u3051\u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8 2 \u304c\u5f53\u305f\u3063\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>\u30e9\u30a4\u30c8\u3092\u99c6\u4f7f\u3059\u308c\u3070\u7dba\u9e97\u306a\u7d75\u3092\u5f97\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u306d\uff01<\/p>\n<p>\u6b21\u306f 3D \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u56de\u8ee2\u3055\u305b\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>\u5de6\u306b\u8868\u793a\u3055\u308c\u3066\u3044\u308b Box \u3092\u5de6\u5965\u306e\u8fba\u3092\u4e2d\u5fc3\u4f4d\u7f6e\u3068\u3057\u3066\u6c34\u5e73\u306b\uff14\uff15\u5ea6\u53f3\u56de\u8ee2\u3055\u305b\u307e\u3059\u3002<\/p>\n<p>\u6b21\u306e\u30b3\u30fc\u30c9\u3092\u5148\u307b\u3069\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u306b\u66f8\u304d\u52a0\u3048\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Box \u3092\u6c34\u5e73\uff14\uff15\u5ea6\u53f3\u56de\u8ee2\u3055\u305b\u308b\u3002\u56de\u8ee2\u306e\u4e2d\u5fc3( \u30d4\u30dc\u30c3\u30c8 )\u306f\u5de6\u5965\u306e\u8fba\u3068\u3059\u308b<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; box.getTransforms().setAll(new Rotate(45.0d, -50.0d, 0.0d, 50.0d, Rotate.Y_AXIS));<\/font><\/p>\n<p>\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/71.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"7\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"7\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/7_thumb1.png\" width=\"644\" height=\"395\"><\/a><\/p>\n<p>javafx.scene.transform.Rotate \u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u751f\u6210\u6642\u306b\u7b2c\u4e00\u5f15\u6570 \u56de\u8ee2\u89d2\u3001\u7b2c\u4e8c\u5f15\u6570\u3001\u7b2c\u4e09\u5f15\u6570\u3001\u7b2c\u56db\u5f15\u6570\u306f\u30d4\u30dc\u30c3\u30c8\u306e\u4f4d\u7f6e\u3092 X, Y ,Z \u8ef8\u3068\u3057\u3066\u8a2d\u5b9a\u3057\u307e\u3059\u3002<\/p>\n<p>\u7b2c\u4e94\u5f15\u6570\u306f\u56de\u8ee2\u8ef8\u3092\u8a2d\u5b9a\u3057\u307e\u3059\u3002<\/p>\n<p>\u305d\u308c\u3089\u3092 javafx.scene.Node \u30af\u30e9\u30b9\u306e getTransforms() \u3067 Box \u306e\u30c8\u30e9\u30f3\u30b9\u30d5\u30a9\u30fc\u30e0\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u53d6\u5f97\u3057 setAll() \u30e1\u30bd\u30c3\u30c9\u3067\u8a2d\u5b9a\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>\u4eca\u56de\u306f setAll() \u30e1\u30bd\u30c3\u30c9\u3092\u4f7f\u3044\u307e\u3057\u305f\u304c\u6b21\u306e\u3088\u3046\u306a\u65b9\u6cd5\u3082\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp; <font color=\"#666666\">box.getTransforms().addAll(new Rotate(45.0d, -50.0d, 0.0d, 50.0d, Rotate.Y_AXIS));<\/font><\/p>\n<p>&nbsp;<\/p>\n<p>\u3053\u308c\u306f\u4eca\u56de\u76ee\u6a19\u3068\u3059\u308b ToyPiano \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u4f7f\u3046\u3068\u554f\u984c\u304c\u51fa\u308b\u306e\u3067\u524d\u8ff0\u306e setAll() \u30e1\u30bd\u30c3\u30c9 \u3092\u4f7f\u7528\u3057\u307e\u3059\u3002<\/p>\n<p>\u305d\u306e\u554f\u984c\u306f\u4f55\u304b\u3068\u8a00\u3046\u3068\u30bf\u30c3\u30c1\u30d7\u30ec\u30b9\u3055\u308c\u305f\u3089\u9375\u76e4\u3092\u3042\u308b\u89d2\u5ea6\u3060\u3051\u30d4\u30dc\u30c3\u30c8\u3092\u8a2d\u5b9a\u3055\u308c\u305f\u3068\u3053\u308d\u304b\u3089\u56de\u8ee2\u3055\u305b\u3001<\/p>\n<p>\u30bf\u30c3\u30c1\u30ea\u30ea\u30fc\u30b9\u3055\u308c\u305f\u3089\u52d5\u304b\u3057\u305f\u5206\u3060\u3051\u623b\u3059\u3068\u3044\u3046\u51e6\u7406\u3092 add() \u30e1\u30bd\u30c3\u30c9\u3092\u4f7f\u3063\u3066\u5b9f\u88c5\u3059\u308b\u3068\u60f3\u5b9a\u3057\u3066\u3044\u305f\u89d2\u5ea6\u3088\u308a\u5927\u304d\u304f( \uff12\u500d )\u52d5\u3044\u3066\u3057\u307e\u3046\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>\u4f55\u6c17\u306b\u52d5\u304b\u3057\u3066\u52d5\u304b\u3057\u305f\u5206\u623b\u3057\u305f\u3089\u3044\u3044\u3084\u3063\u3066\u306e\u306f\u99c4\u76ee\u306a\u3053\u3068\u3082\u3042\u308b\u3093\u3067\u3059\u3002<\/p>\n<p>\u3053\u306e\u3088\u3046\u306a\u3053\u3068\u3092\u907f\u3051\u308b\u305f\u3081 setAll() \u30e1\u30bd\u30c3\u30c9\u3092\u4f7f\u3044\u307e\u3059\u3002<\/p>\n<p>\u3053\u308c\u3067 3D \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u79fb\u52d5\u3001\u56de\u8ee2\u3001\u305d\u3057\u3066\u30ab\u30e1\u30e9\u3068\u30e9\u30a4\u30c8\u306e\u8a2d\u5b9a\u304c\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u308a\u307e\u3057\u305f\u3002<\/p>\n<p>\u3055\u3066\u3001\u3053\u308c\u307e\u3067\u306e\u5b9f\u884c\u7d50\u679c\u3092\u898b\u3066\u6c17\u304c\u4ed8\u3044\u305f\u65b9\u3082\u3044\u3089\u3063\u3057\u3083\u308b\u3068\u601d\u3046\u306e\u3067\u3059\u304c 3D \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306b\u30a2\u30f3\u30c1\u30a8\u30a4\u30ea\u30a2\u30b9\u304c\u52b9\u3044\u3066\u306a\u3044\u3088\u3046\u3067\u3059\u3002<\/p>\n<p>\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u306f\u30a2\u30f3\u30c1\u30a8\u30a4\u30ea\u30a2\u30b9\u306f\u7121\u52b9\u3068\u306a\u3063\u3066\u3044\u308b\u3088\u3046\u306a\u306e\u3067\u3053\u308c\u3092\u6709\u52b9\u306b\u3057\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>\u30d7\u30ed\u30b0\u30e9\u30e0\u306e Scene \u3092\u751f\u6210\u3059\u308b\u30b3\u30fc\u30c9\u3092\u6b21\u306e\u3088\u3046\u306b\u5909\u66f4\u3057\u307e\u3059\u3002<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Scene scene = new Scene(root, 640.0d, 360.0d, true, SceneAntialiasing.BALANCED);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scene.setFill(Color.BLACK);<\/font><\/p>\n<p>\u4f55\u6545\u304b\u30a2\u30f3\u30c1\u30a8\u30a4\u30ea\u30a2\u30b9\u306e\u8a2d\u5b9a\u3092\u3068\u308b\u5f15\u6570\u3092\u4f7f\u3046\u3068\u80cc\u666f\u8272\u306e\u8a2d\u5b9a\u304c\u3067\u304d\u306a\u304f\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>\u305d\u306e\u305f\u3081\u5225\u306b\u80cc\u666f\u8272\u3092\u8a2d\u5b9a\u3059\u308b\u30b3\u30fc\u30c9\u3092\u4ed8\u3051\u52a0\u3048\u307e\u3057\u305f\u3002<\/p>\n<p>\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u4eca\u307e\u3067\u3068\u306f\u9055\u3044\u30a8\u30c3\u30b8\u304c\u6ed1\u3089\u304b\u306b\u8868\u793a\u3055\u308c\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/81.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"8\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"8\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/8_thumb1.png\" width=\"644\" height=\"394\"><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>\u6b21\u306b 3D \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u62e1\u5927\u3084\u30c6\u30af\u30b9\u30c1\u30e3\u306e\u8cbc\u308a\u4ed8\u3051\u306a\u3069\u3082\u8aac\u660e\u3057\u305f\u3044\u3068\u3053\u308d\u3067\u3059\u304c\u4eca\u56de\u306e ToyPiano \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306f\u4f7f\u7528\u3057\u3066\u3044\u306a\u3044\u306e\u3067\u5272\u611b\u3055\u305b\u3066\u3044\u305f\u3060\u304d\u307e\u3059\u3002<\/p>\n<p>\u3068\u8a00\u3044\u3064\u3064\u30fb\u30fb\u30fb\u7c21\u5358\u306b\u3069\u306e\u3088\u3046\u306b\u3059\u308b\u306e\u304b\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n<p>\u8208\u5473\u306e\u7121\u3044\u65b9\u306f\u3053\u306e\u90e8\u5206\u306f\u8aad\u307f\u98db\u3070\u3057\u3066\u304f\u3060\u3055\u3044\u307e\u305b\u3002<\/p>\n<p>\u3067\u306f\u3088\u304f\u898b\u304b\u3051\u308b\u30b5\u30f3\u30d7\u30eb\u3092 JavaFX \u3067\u8a66\u3057\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p><pre title=\"JavaFX3D_Earth.java\">\r\npackage jp.yucchi.javafx3d_earth;\r\n\r\nimport javafx.application.Application;\r\nimport javafx.scene.AmbientLight;\r\nimport javafx.scene.Group;\r\nimport javafx.scene.PerspectiveCamera;\r\nimport javafx.scene.PointLight;\r\nimport javafx.scene.Scene;\r\nimport javafx.scene.SceneAntialiasing;\r\nimport javafx.scene.image.Image;\r\nimport javafx.scene.paint.Color;\r\nimport javafx.scene.paint.PhongMaterial;\r\nimport javafx.scene.shape.DrawMode;\r\nimport javafx.scene.shape.Sphere;\r\nimport javafx.stage.Stage;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic class JavaFX3D_Earth extends Application {\r\n\r\n    @Override\r\n    public void start(Stage primaryStage) {\r\n\r\n        final Group root = new Group();\r\n\r\n        final Sphere sphere = new Sphere(500.0d);\r\n\r\n        \/\/ \u30d5\u30a9\u30f3\u30b7\u30a7\u30fc\u30c7\u30a3\u30f3\u30b0\u3092\u8a2d\u5b9a\r\n        final PhongMaterial sphereMaterial = new PhongMaterial();\r\n\r\n        \/\/ DiffuseMap\r\n        sphereMaterial.setDiffuseMap(\r\n                new Image(this.getClass().getResource(\"resources\/earth_texture.jpg\").toExternalForm(),\r\n                        8_192 \/ 2.0d,\r\n                        4_092 \/ 2.0d,\r\n                        true,\r\n                        true\r\n                )\r\n        );\r\n\r\n        \/\/ BumpMap\r\n        sphereMaterial.setBumpMap(\r\n                new Image(this.getClass().getResource(\"resources\/earth_normalmap.jpg\").toExternalForm(),\r\n                        8_192 \/ 2.0d,\r\n                        4_092 \/ 2.0d,\r\n                        true,\r\n                        true\r\n                )\r\n        );\r\n\r\n        \/\/ SpecularMap\r\n        sphereMaterial.setSpecularMap(\r\n                new Image(this.getClass().getResource(\"resources\/earth_specularmap.jpg\").toExternalForm(),\r\n                        8_192 \/ 2.0d,\r\n                        4_092 \/ 2.0d,\r\n                        true,\r\n                        true\r\n                )\r\n        );\r\n\r\n        \/\/ \u30de\u30c6\u30ea\u30a2\u30eb\u3092\u8a2d\u5b9a\r\n        sphere.setMaterial(sphereMaterial);\r\n        \/\/ \u30c9\u30ed\u30fc\u30e2\u30fc\u30c9\u3092\u8a2d\u5b9a\r\n        sphere.setDrawMode(DrawMode.FILL);\r\n\r\n        \/\/ \u900f\u8996\u6295\u5f71\u30ab\u30e1\u30e9\r\n        final PerspectiveCamera cam = new PerspectiveCamera(true);\r\n        \/\/ Field of View \r\n        cam.setFieldOfView(45.5d);\r\n        \/\/ Clipping Planes\r\n        cam.setNearClip(1.0d);\r\n        cam.setFarClip(1_000_000.0d);\r\n\r\n        \/\/ \u30ab\u30e1\u30e9\u3092 1500 \u5f8c\u9000\u3055\u305b\u308b\u3002(Z \u8ef8\u3092 -1500)\r\n        cam.setTranslateZ(-1_500.0d);\r\n\r\n        \/\/ \u30a2\u30f3\u30d3\u30a8\u30f3\u30c8\u30e9\u30a4\u30c8\r\n        AmbientLight ambient = new AmbientLight();\r\n        ambient.setColor(Color.rgb(90, 90, 90, 0.6));\r\n\r\n        \/\/ \u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\r\n        PointLight point = new PointLight();\r\n        point.setColor(Color.WHITE);\r\n\r\n        \/\/ \u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u3092\u79fb\u52d5\r\n        point.setTranslateX(-1_800.0d);\r\n        point.setTranslateY(-1_300.0d);\r\n        point.setTranslateZ(-1_800.0d);\r\n\r\n        root.getChildren().addAll(sphere, ambient, point);\r\n\r\n        Scene scene = new Scene(root, 1_024, 768, true, SceneAntialiasing.BALANCED);\r\n\r\n        scene.setFill(Color.BLACK);\r\n\r\n        scene.setCamera(cam);\r\n\r\n        primaryStage.setTitle(\"JavaFX 3D EARTH\");\r\n        primaryStage.setScene(scene);\r\n        primaryStage.show();\r\n    }\r\n\r\n    \/**\r\n     * @param args the command line arguments\r\n     *\/\r\n    public static void main(String[] args) {\r\n        launch(args);\r\n    }\r\n\r\n}\r\n\r\n\r\n<\/pre>\n<\/p>\n<p>\u30c6\u30af\u30b9\u30c1\u30e3\u3092\u8cbc\u308b\u306b\u306f javafx.scene.paint.PhongMaterial \u30af\u30e9\u30b9\u3092\u4f7f\u7528\u3057\u307e\u3059\u3002<\/p>\n<p>PhongMaterial \u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3092\u751f\u6210\u3059\u308b\u3068\u304d\u306b\u30b3\u30f3\u30b9\u30c8\u30e9\u30af\u30bf\u306e\u5f15\u6570\u3068\u3057\u3066\u6e21\u3059\u304b\u3001<\/p>\n<p>\u5404\u7a2e\u30a4\u30e1\u30fc\u30b8\u3092 javafx.scene.paint.PhongMaterial \u30af\u30e9\u30b9\u306e\u8a2d\u5b9a\u30e1\u30bd\u30c3\u30c9<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp; setDiffuseMap(Image value)<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp; setBumpMap(Image value)<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp; setSpecularMap(Image value)<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp; setSelfIlluminationMap(Image value)<\/font><\/p>\n<p>\u3092\u4f7f\u3063\u3066\u8a2d\u5b9a\u3059\u308b\u3060\u3051\u3067\u3059\u3002<\/p>\n<p>\u975e\u5e38\u306b\u304a\u624b\u8efd\u306b\u8a2d\u5b9a\u3067\u304d\u307e\u3059\u3002<\/p>\n<p>\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/9.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"9\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"9\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/9_thumb.png\" width=\"620\" height=\"484\"><\/a><\/p>\n<p>\u305d\u308c\u305e\u308c\u304c\u3069\u306e\u3088\u3046\u306b\u4f5c\u7528\u3057\u3066\u3044\u308b\u306e\u304b\u5c11\u3057\u307f\u3066\u304a\u304d\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>setDiffuseMap(Image value) \u3060\u3051\u3092\u8a2d\u5b9a\u3057\u305f\u5834\u5408\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u3001<\/p>\n<p>\u3067\u3053\u307c\u3053\u611f\u304c\u307e\u3063\u305f\u304f\u306a\u304f\u306e\u3063\u307a\u308a\u3057\u305f\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/10.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"10\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"10\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/10_thumb.png\" width=\"622\" height=\"484\"><\/a><\/p>\n<p>\u4f7f\u3063\u305f\u30a4\u30e1\u30fc\u30b8\u30d5\u30a1\u30a4\u30eb\u306f\u3053\u308c\u3067\u3059\u3002(\u30b5\u30a4\u30ba\u306f\u9055\u3044\u307e\u3059)<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/11.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"11\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"11\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/11_thumb.jpg\" width=\"644\" height=\"325\"><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>setBumpMap(Image value) \u3092\u8a2d\u5b9a\u3059\u308b\u3053\u3068\u306b\u3088\u308a\u3067\u3053\u307c\u3053\u611f\u3092\u6f14\u51fa\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n<p>\u30a4\u30e1\u30fc\u30b8\u30d5\u30a1\u30a4\u30eb\u306f\u3053\u308c\u3092\u4f7f\u7528\u3057\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/12.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"12\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"12\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/12_thumb.jpg\" width=\"644\" height=\"325\"><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/13.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"13\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"13\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/13_thumb.png\" width=\"622\" height=\"484\"><\/a><\/p>\n<p>setSpecularMap(Image value) \u306f\u53cd\u5c04\u5149\u3092\u5236\u5fa1\u3059\u308b\u3082\u306e\u3067\u6b21\u306e\u3088\u3046\u306a\u30a4\u30e1\u30fc\u30b8\u30d5\u30a1\u30a4\u30eb\u3092\u4f7f\u7528\u3057\u307e\u3059\u3002<\/p>\n<p>\u9ed2\u304f\u306a\u3063\u3066\u3044\u308b\u6240\u306f\u53cd\u5c04\u5149\u3092\u51fa\u3055\u306a\u3044\u3088\u3046\u3067\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/14.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"14\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"14\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/14_thumb.jpg\" width=\"644\" height=\"325\"><\/a><\/p>\n<p>\u3067\u306f SpecularMap \u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u306a\u3044\u5834\u5408\u306f\u3069\u3046\u306a\u308b\u306e\u304b\u307f\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>setSpecularMap(Image value) \u3092\u672a\u8a2d\u5b9a\u3068\u3057\u305f\u3046\u3048\u3067\u30d7\u30ed\u30b0\u30e9\u30e0\u306b\u53cd\u5c04\u5149\u306e\u8a2d\u5b9a\u3092\u52a0\u3048\u307e\u3059\u3002<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphereMaterial.setSpecularColor(Color.RED);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphereMaterial.setSpecularPower(3.0d);<\/font><\/p>\n<p>\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>\u8d64\u3044\u53cd\u5c04\u5149\u304c\u3057\u3063\u304b\u308a\u3068\u8868\u793a\u3055\u308c\u3066\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/15.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"15\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"15\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/15_thumb.png\" width=\"620\" height=\"484\"><\/a><\/p>\n<p>setSpecularMap(Image value) \u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u308c\u3070\u53cd\u5c04\u5149\u3092\u5236\u5fa1\u53ef\u80fd\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>setSpecularMap(Image value) \u3092\u9069\u7528\u3057\u3066\u5b9f\u884c\u3059\u308b\u3068\u4e0b\u56f3\u306e\u3088\u3046\u306b\u53cd\u5c04\u5149\u304c\u9069\u7528\u3055\u308c\u3066\u3044\u308b\u90e8\u5206\u304c\u9650\u5b9a\u3067\u304d\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/15b.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"15b\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"15b\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/15b_thumb.png\" width=\"622\" height=\"484\"><\/a><\/p>\n<p>\u3061\u3087\u3063\u3068\u89e3\u308a\u3065\u3089\u3044\u3051\u3069\u7070\u8272\u306e\u90e8\u5206\u3060\u3051\u8584\u304f\u53cd\u5c04\u3055\u308c\u3066\u3044\u308b\u306e\u304c\u78ba\u8a8d\u3067\u304d\u307e\u3059\u3002<\/p>\n<p>\u89e3\u308a\u3084\u3059\u304f\u3059\u308b\u305f\u3081\u306b SpecularMap \u30a4\u30e1\u30fc\u30b8\u30d5\u30a1\u30a4\u30eb\u3092\u4e0b\u56f3\u306e\u3088\u3046\u306b\u53cd\u5c04\u30d9\u30fc\u30b9\u8272\u3092\u7070\u8272\u304b\u3089\u767d\u8272\u3078\u3068\u5909\u66f4\u3057\u3066\u307f\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/15c.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"15c\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"15c\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/15c_thumb.jpg\" width=\"644\" height=\"325\"><\/a><\/p>\n<p>\u3053\u308c\u3067\u5b9f\u884c\u3059\u308b\u3068\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/15d.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"15d\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"15d\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/15d_thumb.png\" width=\"620\" height=\"484\"><\/a><\/p>\n<p>SpecularMap \u3092\u4e0a\u624b\u304f\u6d3b\u7528\u3059\u308c\u3070\u7e4a\u7d30\u306a\u63cf\u753b\u304c\u53ef\u80fd\u3068\u306a\u308a\u305d\u3046\u3067\u3059\u3002<\/p>\n<p>\u305d\u308c\u3067\u306f DiffuseColor \u3092\u8a2d\u5b9a\u3057\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>\u30d7\u30ed\u30b0\u30e9\u30e0\u306b\u6b21\u306e\u30b3\u30fc\u30c9\u3092\u66f8\u304d\u52a0\u3048\u307e\u3059\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color=\"#666666\">sphereMaterial.setDiffuseColor(Color.ORANGERED);<\/font><\/p>\n<p>\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u5b9f\u884c\u3059\u308b\u3068 \u8a2d\u5b9a\u3057\u305f DiffuseColor \u30aa\u30ec\u30f3\u30b8\u30ec\u30c3\u30c9\u304c\u9069\u7528\u3055\u308c\u8d64\u3063\u307d\u3044\u5730\u7403\u304c\u8868\u793a\u3055\u308c\u307e\u3059\u3002<\/p>\n<p>\u9762\u767d\u3044\u3067\u3059\u306d\u3002<\/p>\n<p>\u307e\u308b\u3067\u30ac\u30df\u30e9\u30b9\u5e1d\u56fd\u306b\u653b\u6483\u3055\u308c\u3066\u653e\u5c04\u80fd\u6c5a\u67d3\u3055\u308c\u305f\u5730\u7403\u306e\u3088\u3046\u3067\u3059\u3002ww<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/16.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"16\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"16\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/16_thumb.png\" width=\"622\" height=\"484\"><\/a><\/p>\n<p>\u6700\u5f8c\u306b setSelfIlluminationMap(Image value) \u3092\u8a66\u3057\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>\u3053\u308c\u4f7f\u3044\u9053\u304c\u826f\u304f\u89e3\u3089\u306a\u3044\u306e\u3067\u3059\u304c\u540d\u524d\u304b\u3089\u3059\u308b\u3068\u81ea\u767a\u5149\u306e\u3088\u3046\u3067\u3059\u3002<\/p>\n<p>\u306a\u306e\u3067\u30e9\u30a4\u30c8\u3092\u7121\u3057\u306b\u3057\u3066\u3001\u30de\u30c6\u30ea\u30a2\u30eb\u306e\u8a2d\u5b9a\u306f setSelfIlluminationMap(Image value) \u3060\u3051\u306b\u3057\u307e\u3057\u305f\u3002<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ SelfIlluminationMap<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphereMaterial.setSelfIlluminationMap(<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Image(this.getClass().getResource(&#8220;resources\/earth_texture.jpg&#8221;).toExternalForm(),<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8_192 \/ 2.0d,<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4_092 \/ 2.0d,<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; true,<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; true<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );<\/font><\/p>\n<p><font color=\"#666666\"><\/font>&nbsp;<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; root.getChildren().addAll(sphere);<\/font><\/p>\n<p>&nbsp;<\/p>\n<p>\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3057\u305f\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/17.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"17\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"17\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/17_thumb.png\" width=\"622\" height=\"484\"><\/a><\/p>\n<p>\u3084\u3063\u3071\u308a\u81ea\u767a\u5149\u306e\u8a2d\u5b9a\u306e\u3088\u3046\u3067\u3059\u3002<\/p>\n<p>\u767a\u5149\u8272\u3084\u5f37\u3055\u306e\u8a2d\u5b9a\u304c\u3067\u304d\u306a\u3044\u304b\u3068\u8abf\u3079\u3066\u307f\u305f\u306e\u3067\u3059\u304c\u89e3\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002<\/p>\n<p>\u4ee5\u4e0a\u30c6\u30af\u30b9\u30c1\u30e3\u306e\u8cbc\u308a\u65b9\u3092\u7c21\u5358\u306b\u8aac\u660e\u3055\u305b\u3066\u3044\u305f\u3060\u304d\u307e\u3057\u305f\u3002<\/p>\n<p>ToyPiano \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306f\u30c6\u30af\u30b9\u30c1\u30e3\u306f\u8cbc\u3063\u3066\u306a\u3044\u306e\u3067\u86c7\u8db3\u3068\u306a\u3063\u3066\u3057\u307e\u3044\u307e\u3057\u305f\u304c\u304a\u6c17\u306b\u5165\u308a\u306e\u30c6\u30af\u30b9\u30c1\u30e3\u3092\u6301\u3063\u3066\u3044\u308b\u65b9\u306f\u8cbc\u3063\u3066\u304a\u697d\u3057\u307f\u304f\u3060\u3055\u3044\u3002<\/p>\n<p>\u86c7\u8db3\u3064\u3044\u3067\u306b 3D \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u62e1\u5927\u7e2e\u5c0f\u3082\u3084\u3063\u3066\u304a\u304d\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>Sphere \u304c\u30de\u30a6\u30b9\u30af\u30ea\u30c3\u30af\u3055\u308c\u305f\u5ea7\u6a19\u4f4d\u7f6e\u3092\u53d6\u5f97\u3057\u305d\u308c\u3089\u306e\u5024\u3092\u9069\u5f53\u306b\u52a0\u5de5\u3057\u3066\u62e1\u5927\u7e2e\u5c0f\u3055\u305b\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>\u30d7\u30ed\u30b0\u30e9\u30e0\u306b\u4e0b\u8a18\u30b3\u30fc\u30c9\u3092\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scene.setOnMouseClicked(event -&gt; {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PickResult pickResult = event.getPickResult();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (pickResult.getIntersectedNode() == sphere) {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point3D point3d = pickResult.getIntersectedPoint();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (point3d.getX() != 0.0d &amp;&amp; point3d.getY() != 0.0d &amp;&amp; point3d.getZ() != 0.0d) {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphere.setScaleX(abs(point3d.getX() \/ 500.0d) * 1.2d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphere.setScaleY(abs(point3d.getY() \/ 500.0d) * 1.2d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphere.setScaleZ(abs(point3d.getZ() \/ 500.0d) * 1.2d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphere.setScaleX(0.5d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphere.setScaleY(0.5d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphere.setScaleZ(0.5d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphere.setScaleX(1.0d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphere.setScaleY(1.0d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphere.setScaleZ(1.0d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<\/font><\/p>\n<p>&nbsp;<\/p>\n<p>\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/18.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"18\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"18\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/18_thumb.png\" width=\"623\" height=\"484\"><\/a><\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/19.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"19\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"19\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/19_thumb.png\" width=\"621\" height=\"484\"><\/a><\/p>\n<p>PickResult \u30af\u30e9\u30b9\u3092\u4f7f\u3044 Scene \u306e\u30af\u30ea\u30c3\u30af\u3055\u308c\u305f\u3082\u306e\u304c Sphere \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304b\u3069\u3046\u304b<\/p>\n<p>getIntersectedNode() \u30e1\u30bd\u30c3\u30c9\u3067\u5224\u5b9a\u3057\u3001\u305d\u3046\u3067\u3042\u308c\u3070<\/p>\n<p>getIntersectedPoint() \u30e1\u30bd\u30c3\u30c9\u3067 Point3D \u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3092\u6e21\u3057\u307e\u3059\u3002<\/p>\n<p>Point3D \u30af\u30e9\u30b9\u3092\u4f7f\u3044\u3001X, Y, Z \u5ea7\u6a19\u4f4d\u7f6e\u60c5\u5831\u3092\u53d6\u5f97\u3057\u3066\u305d\u308c\u3089\u306e\u5024\u306e\u7d76\u5bfe\u5024\u3092 Sphere \u306e\u534a\u5f84\u3067\u5272\u308a\u305d\u3057\u3066 1.2 \u500d\u3057\u3066\u307e\u3059\u3002<\/p>\n<p>javafx.scene.Node \u30af\u30e9\u30b9\u306e\u30e1\u30bd\u30c3\u30c9\u3092\u5229\u7528\u3057\u3066\u305d\u308c\u305e\u308c X, Y, Z \u5ea7\u6a19\u5024\u306b\u9069\u7528\u3057\u3066\u307e\u3059\u3002<\/p>\n<p>setScaleX(double value)<\/p>\n<p>setScaleY(double value)<\/p>\n<p>setScaleZ(double value)<\/p>\n<p>\u4e0a\u8a18\u30d7\u30ed\u30b0\u30e9\u30e0\u3067\u306f X, Y, Z \u8ef8\u306e\u4f55\u308c\u304b\u306e\u5ea7\u6a19\u4f4d\u7f6e\u304c 0 \u306a\u3089\u62e1\u5927\u7e2e\u5c0f\u3092 0.5 \u500d\u3059\u308b\u3088\u3046\u306b\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>Sphere \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304c\u30af\u30ea\u30c3\u30af\u3055\u308c\u3066\u306a\u3051\u308c\u3070\u62e1\u5927\u7e2e\u5c0f\u306f\u5143\u306b\uff081.0 \u500d)\u306b\u623b\u3057\u307e\u3059\u3002<\/p>\n<p>\u62e1\u5927\u7e2e\u5c0f\u3082\u7c21\u5358\u306b\u3067\u304d\u307e\u3059\u306d\uff01<\/p>\n<p>\u3064\u3044\u3067\u3060\u304b\u3089\u56de\u8ee2\u3055\u305b\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>Z \u8ef8\u3092 23.5 \u5ea6\u50be\u3051\u3066\u53cd\u6642\u8a08\u56de\u308a\u306b\u56de\u8ee2\u3055\u305b\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>\u30d7\u30ed\u30b0\u30e9\u30e0\u306b\u4e0b\u8a18\u306e\u3088\u3046\u307f\u5909\u66f4\u3057\u307e\u3059\u3002<\/p>\n<p><pre title=\"JavaFX3D_Earth.java\">\r\npackage jp.yucchi.javafx3d_earth;\r\n\r\nimport static java.lang.Math.abs;\r\nimport javafx.animation.AnimationTimer;\r\nimport javafx.application.Application;\r\nimport javafx.beans.property.DoubleProperty;\r\nimport javafx.beans.property.SimpleDoubleProperty;\r\nimport javafx.geometry.Point3D;\r\nimport javafx.scene.AmbientLight;\r\nimport javafx.scene.Group;\r\nimport javafx.scene.PerspectiveCamera;\r\nimport javafx.scene.PointLight;\r\nimport javafx.scene.Scene;\r\nimport javafx.scene.SceneAntialiasing;\r\nimport javafx.scene.image.Image;\r\nimport javafx.scene.input.PickResult;\r\nimport javafx.scene.paint.Color;\r\nimport javafx.scene.paint.PhongMaterial;\r\nimport javafx.scene.shape.DrawMode;\r\nimport javafx.scene.shape.Sphere;\r\nimport javafx.scene.transform.Rotate;\r\nimport javafx.stage.Stage;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic class JavaFX3D_Earth extends Application {\r\n\r\n    @Override\r\n    public void start(Stage primaryStage) {\r\n\r\n        final Group root = new Group();\r\n\r\n        final Sphere sphere = new Sphere(500.0d);\r\n\r\n        \/\/ \u30d5\u30a9\u30f3\u30b7\u30a7\u30fc\u30c7\u30a3\u30f3\u30b0\u3092\u8a2d\u5b9a\r\n        final PhongMaterial sphereMaterial = new PhongMaterial();\r\n\r\n        \/\/ DiffuseMap\r\n        sphereMaterial.setDiffuseMap(\r\n                new Image(this.getClass().getResource(\"resources\/earth_texture.jpg\").toExternalForm(),\r\n                        8192 \/ 2d,\r\n                        4092 \/ 2d,\r\n                        true,\r\n                        true\r\n                )\r\n        );\r\n\r\n        \/\/ BumpMap\r\n        sphereMaterial.setBumpMap(\r\n                new Image(this.getClass().getResource(\"resources\/earth_normalmap.jpg\").toExternalForm(),\r\n                        8192 \/ 2d,\r\n                        4092 \/ 2d,\r\n                        true,\r\n                        true\r\n                )\r\n        );\r\n\r\n        \/\/ SpecularMap\r\n        sphereMaterial.setSpecularMap(\r\n                new Image(this.getClass().getResource(\"resources\/earth_specularmap.jpg\").toExternalForm(),\r\n                        8192 \/ 2d,\r\n                        4092 \/ 2d,\r\n                        true,\r\n                        true\r\n                )\r\n        );\r\n\r\n\/\/        \/\/ SelfIlluminationMap\r\n\/\/        sphereMaterial.setSelfIlluminationMap(\r\n\/\/                new Image(this.getClass().getResource(\"resources\/earth_texture.jpg\").toExternalForm(),\r\n\/\/                        8192 \/ 2d,\r\n\/\/                        4092 \/ 2d,\r\n\/\/                        true,\r\n\/\/                        true\r\n\/\/                )\r\n\/\/        );\r\n        sphereMaterial.setSpecularColor(Color.WHITE);\r\n\r\n        sphereMaterial.setSpecularPower(2.5d);\r\n\r\n\/\/        sphereMaterial.setDiffuseColor(Color.ORANGERED);\r\n        \/\/ \u30de\u30c6\u30ea\u30a2\u30eb\u3092\u8a2d\u5b9a\r\n        sphere.setMaterial(sphereMaterial);\r\n\r\n        \/\/ \u30c9\u30ed\u30fc\u30e2\u30fc\u30c9\u3092\u8a2d\u5b9a\r\n        sphere.setDrawMode(DrawMode.FILL);\r\n\r\n        \/\/ \u900f\u8996\u6295\u5f71\u30ab\u30e1\u30e9\r\n        final PerspectiveCamera cam = new PerspectiveCamera(true);\r\n        \/\/ Field of View \r\n        cam.setFieldOfView(45.5d);\r\n        \/\/ Clipping Planes\r\n        cam.setNearClip(1.0d);\r\n        cam.setFarClip(1_000_000.0d);\r\n\r\n        \/\/ \u30ab\u30e1\u30e9\u3092 1500 \u5f8c\u9000\u3055\u305b\u308b\u3002(Z \u8ef8\u3092 -1500)\r\n        cam.setTranslateZ(-1_500.0d);\r\n\r\n        \/\/ \u30a2\u30f3\u30d3\u30a8\u30f3\u30c8\u30e9\u30a4\u30c8\r\n        AmbientLight ambient = new AmbientLight();\r\n        ambient.setColor(Color.rgb(90, 90, 90, 0.6));\r\n\r\n        \/\/ \u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\r\n        PointLight point = new PointLight();\r\n        point.setColor(Color.WHITE);\r\n\r\n        \/\/ \u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u3092\u79fb\u52d5\r\n        point.setTranslateX(-1_800.0d);\r\n        point.setTranslateY(-1_300.0d);\r\n        point.setTranslateZ(-1_800.0d);\r\n\r\n        root.getChildren().addAll(sphere, ambient, point);\r\n\r\n        Scene scene = new Scene(root, 1_024, 768, true, SceneAntialiasing.BALANCED);\r\n\r\n        scene.setFill(Color.BLACK);\r\n\r\n        scene.setCamera(cam);\r\n\r\n        scene.setOnMouseClicked(event -> {\r\n            PickResult pickResult = event.getPickResult();\r\n            if (pickResult.getIntersectedNode() == sphere) {\r\n                Point3D point3d = pickResult.getIntersectedPoint();\r\n                if (point3d.getX() != 0.0d && point3d.getY() != 0.0d && point3d.getZ() != 0.0d) {\r\n                    sphere.setScaleX(abs(point3d.getX() \/ 500.0d) * 1.2d);\r\n                    sphere.setScaleY(abs(point3d.getY() \/ 500.0d) * 1.2d);\r\n                    sphere.setScaleZ(abs(point3d.getZ() \/ 500.0d) * 1.2d);\r\n                } else {\r\n                    sphere.setScaleX(0.5d);\r\n                    sphere.setScaleY(0.5d);\r\n                    sphere.setScaleZ(0.5d);\r\n                }\r\n            } else {\r\n                sphere.setScaleX(1.0d);\r\n                sphere.setScaleY(1.0d);\r\n                sphere.setScaleZ(1.0d);\r\n            }\r\n        });\r\n\r\n\t\/\/ \u3053\u306e\u90e8\u5206\u4e0d\u8981\u3060\u3051\u3069\u3088\u304f\u3042\u308b\u9593\u9055\u3044\u306e\u8aac\u660e\u306e\u305f\u3081\r\n        final DoubleProperty angleX = new SimpleDoubleProperty(0.0d);\r\n        final DoubleProperty angleY = new SimpleDoubleProperty(0.0d);\r\n        final DoubleProperty angleZ = new SimpleDoubleProperty(0.0d);\r\n\r\n        Rotate xRotate;\r\n        Rotate yRotate;\r\n        Rotate zRotate;\r\n\r\n        sphere.getTransforms().setAll(\r\n                xRotate = new Rotate(0.0d, Rotate.X_AXIS),\r\n                yRotate = new Rotate(0.0d, Rotate.Y_AXIS),\r\n                zRotate = new Rotate(0.0d, Rotate.Z_AXIS));\r\n\r\n        xRotate.angleProperty().bind(angleX);\r\n        yRotate.angleProperty().bind(angleY);\r\n        zRotate.angleProperty().bind(angleZ);\r\n\r\n        AnimationTimer animation = new AnimationTimer() {\r\n\r\n            \/\/ \u524d\u56de\u6642\u9593\r\n            private long previousHandledTime;\r\n            \/\/ \u89d2\u5ea6\r\n            private double angle;\r\n            \/\/ \u56de\u8ee2\u901f\u5ea6\r\n            private final DoubleProperty angularVelocityProperty = new SimpleDoubleProperty(10.0d);\r\n\r\n            @Override\r\n            public void handle(long now) {\r\n\r\n                if (previousHandledTime == 0) {\r\n                    previousHandledTime = now;\r\n                    return;\r\n                }\r\n\r\n                angle += angularVelocityProperty.get() * (now - previousHandledTime) \/ 1_000_000_000;\r\n\r\n                previousHandledTime = now;\r\n\r\n                \/\/ \uff12\uff13\uff0e\uff15\u5ea6\u50be\u3051\u3066\u81ea\u8ee2\u3055\u305b\u308b\u3002\r\n                sphere.getTransforms().setAll(new Rotate(23.5d, Rotate.Z_AXIS), new Rotate(-angle, Rotate.Y_AXIS));\r\n\r\n            }\r\n        };\r\n\r\n        animation.start();\r\n\r\n        primaryStage.setTitle(\"JavaFX 3D EARTH\");\r\n        primaryStage.setScene(scene);\r\n        primaryStage.show();\r\n    }\r\n\r\n    \/**\r\n     * @param args the command line arguments\r\n     *\/\r\n    public static void main(String[] args) {\r\n        launch(args);\r\n    }\r\n\r\n}\r\n\r\n\r\n\r\n<\/pre>\n<\/p>\n<p>\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u306e\u52d5\u753b\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><iframe loading=\"lazy\" height=\"480\" src=\"\/\/www.youtube.com\/embed\/Ph0JdkHUUmM?rel=0\" frameborder=\"0\" width=\"640\" allowfullscreen><\/iframe> <\/p>\n<p>AnimationTimer \u3067\u5730\u7403\u3092 23.5 \u5ea6\u50be\u3051\u3066\u53cd\u6642\u8a08\u56de\u308a\u306b\u56de\u8ee2\u3055\u305b\u3066\u3044\u308b\u30b3\u30fc\u30c9\u306f\u6b21\u306e\u90e8\u5206\u3067\u3059\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color=\"#666666\">\/\/ \uff12\uff13\uff0e\uff15\u5ea6\u50be\u3051\u3066\u81ea\u8ee2\u3055\u305b\u308b\u3002<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sphere.getTransforms().setAll(new Rotate(23.5d, Rotate.Z_AXIS), new Rotate(-angle, Rotate.Y_AXIS));<\/font><\/p>\n<p>\u3053\u308c\u3092\u6b21\u306e\u3088\u3046\u306b\u8a18\u8ff0\u3057\u3066\u3057\u307e\u3046\u3068\u601d\u3044\u901a\u308a\u306b\u3044\u304d\u307e\u305b\u3093\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color=\"#666666\">angleZ.set(23.50d);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; angleY.set(angle);<\/font><\/p>\n<p>\u3046\u3063\u304b\u308a\u3053\u308c\u3084\u3063\u3066\u3057\u307e\u3046\u3068 Z \u8ef8\u304c 23.5 \u5ea6\u50be\u3044\u3066\u304b\u3089\u6c34\u5e73\u306b\u53cd\u6642\u8a08\u56de\u308a\u306b\u56de\u3063\u3066\u3057\u307e\u3044\u307e\u3059\u3002<\/p>\n<p>\u3053\u308c\u306f\u3053\u306e\u5f8c\u306e\u30ab\u30e1\u30e9\u3092\u52d5\u304b\u3059\u5834\u5408\u3067\u3082\u540c\u3058\u3088\u3046\u306b\u6ce8\u610f\u304c\u5fc5\u8981\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>\u305b\u3063\u304b\u304f\u3053\u3053\u307e\u3067\u8a66\u3057\u305f\u3053\u3068\u3060\u3057\u3082\u3046\u5c11\u3057\u3060\u3051\u5bc4\u308a\u9053\u3092\u3057\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>\u81ea\u8ee2\u3059\u308b\u5730\u7403\u306e\u5468\u308a\u306b\u6708\u3092\u516c\u8ee2\u3055\u305b\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>\u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u306f\u592a\u967d\u306e\u4f4d\u7f6e\u3068\u3057\u307e\u3059\u3002\uff08\u5927\u304d\u3055\u3084\u8ddd\u96e2\u306b\u6b63\u78ba\u306a\u5024\u306f\u4f7f\u3063\u3066\u306a\u3044\u3067\u3059\u3002\u9069\u5f53\u3067\u3059\u3002\uff09<\/p>\n<p>\u4eca\u307e\u3067\u306e\u6280\u8853\u3067\u3055\u3089\u3063\u3068\u3067\u304d\u3066\u3057\u307e\u3044\u307e\u3059\u3002<\/p>\n<p><pre title=\"JavaFX3D_Earth.java\">\r\npackage jp.yucchi.earth_moon;\r\n\r\nimport javafx.animation.AnimationTimer;\r\nimport javafx.application.Application;\r\nimport javafx.beans.property.DoubleProperty;\r\nimport javafx.beans.property.SimpleDoubleProperty;\r\nimport javafx.scene.AmbientLight;\r\nimport javafx.scene.Group;\r\nimport javafx.scene.PerspectiveCamera;\r\nimport javafx.scene.PointLight;\r\nimport javafx.scene.Scene;\r\nimport javafx.scene.SceneAntialiasing;\r\nimport javafx.scene.image.Image;\r\nimport javafx.scene.paint.Color;\r\nimport javafx.scene.paint.PhongMaterial;\r\nimport javafx.scene.shape.DrawMode;\r\nimport javafx.scene.shape.Sphere;\r\nimport javafx.scene.transform.Rotate;\r\nimport javafx.stage.Stage;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic class Earth_Moon extends Application {\r\n\r\n    static final double DISTANCE_MOON = 400.0d;\r\n\r\n    static final double DISTANCE_SUN = 900.0d;\r\n\r\n    \/\/ \u5ea7\u6a19\r\n    private double anchorAngleX;\r\n    private double anchorAngleY;\r\n    private final DoubleProperty angleX = new SimpleDoubleProperty(0d);\r\n    private final DoubleProperty angleY = new SimpleDoubleProperty(0d);\r\n    private final DoubleProperty angleZ = new SimpleDoubleProperty(0d);\r\n    private double anchorX;\r\n    private double anchorY;\r\n\r\n    @Override\r\n    public void start(Stage primaryStage) {\r\n\r\n        final Group root = new Group();\r\n\r\n        \/\/ Earth\r\n        final Sphere earth = new Sphere(100.0d);\r\n        \/\/ \u30d5\u30a9\u30f3\u30b7\u30a7\u30fc\u30c7\u30a3\u30f3\u30b0\u3092\u8a2d\u5b9a\r\n        final PhongMaterial earthMaterial = new PhongMaterial();\r\n        \/\/ DiffuseMap\r\n        earthMaterial.setDiffuseMap(\r\n                new Image(this.getClass().getResource(\"resources\/earth_texture.jpg\").toExternalForm(),\r\n                        8_192 \/ 2.0d,\r\n                        4_092 \/ 2.0d,\r\n                        true,\r\n                        true\r\n                )\r\n        );\r\n        \/\/ BumpMap\r\n        earthMaterial.setBumpMap(\r\n                new Image(this.getClass().getResource(\"resources\/earth_normalmap.jpg\").toExternalForm(),\r\n                        8_192 \/ 2.0d,\r\n                        4_092 \/ 2.0d,\r\n                        true,\r\n                        true\r\n                )\r\n        );\r\n        \/\/ SpecularMap\r\n        earthMaterial.setSpecularMap(\r\n                new Image(this.getClass().getResource(\"resources\/earth_specularmap.jpg\").toExternalForm(),\r\n                        8_192 \/ 2.0d,\r\n                        4_092 \/ 2.0d,\r\n                        true,\r\n                        true\r\n                )\r\n        );\r\n        \/\/ \u53cd\u5c04\u5149\u8272\u8a2d\u5b9a\r\n        earthMaterial.setSpecularColor(Color.WHITE);\r\n        \/\/ \u53cd\u5c04\u5149\u306e\u5f37\u3055\u8a2d\u5b9a\r\n        earthMaterial.setSpecularPower(2.5d);\r\n        \/\/ \u30de\u30c6\u30ea\u30a2\u30eb\u3092\u8a2d\u5b9a\r\n        earth.setMaterial(earthMaterial);\r\n        \/\/ \u30c9\u30ed\u30fc\u30e2\u30fc\u30c9\u3092\u8a2d\u5b9a\r\n        earth.setDrawMode(DrawMode.FILL);\r\n\r\n        \/\/ Moon\r\n        final Sphere moon = new Sphere(50.0d);\r\n        \/\/ \u30d5\u30a9\u30f3\u30b7\u30a7\u30fc\u30c7\u30a3\u30f3\u30b0\u3092\u8a2d\u5b9a\r\n        final PhongMaterial moonMaterial = new PhongMaterial();\r\n        \/\/ DiffuseMap\r\n        moonMaterial.setDiffuseMap(\r\n                new Image(this.getClass().getResource(\"resources\/moon.jpg\").toExternalForm(),\r\n                        2_500 \/ 2.0d,\r\n                        1_250 \/ 2.0d,\r\n                        true,\r\n                        true\r\n                )\r\n        );\r\n        \/\/ \u53cd\u5c04\u5149\u8272\u8a2d\u5b9a\r\n        moonMaterial.setSpecularColor(Color.LIGHTYELLOW);\r\n        \/\/ \u30de\u30c6\u30ea\u30a2\u30eb\u3092\u8a2d\u5b9a\r\n        moon.setMaterial(moonMaterial);\r\n        \/\/ \u30c9\u30ed\u30fc\u30e2\u30fc\u30c9\u3092\u8a2d\u5b9a\r\n        moon.setDrawMode(DrawMode.FILL);\r\n\r\n        \/\/ Sun\r\n        final Sphere sun = new Sphere(100.0d);\r\n        \/\/ \u30d5\u30a9\u30f3\u30b7\u30a7\u30fc\u30c7\u30a3\u30f3\u30b0\u3092\u8a2d\u5b9a\r\n        final PhongMaterial sunMaterial = new PhongMaterial();\r\n        \/\/ SelfIlluminationMap\r\n        sunMaterial.setSelfIlluminationMap(\r\n                new Image(this.getClass().getResource(\"resources\/sun.jpg\").toExternalForm(),\r\n                        3_000.0d,\r\n                        1_500.0d,\r\n                        true,\r\n                        true\r\n                )\r\n        );\r\n        \/\/ \u30de\u30c6\u30ea\u30a2\u30eb\u3092\u8a2d\u5b9a\r\n        sun.setMaterial(sunMaterial);\r\n        \/\/ \u30c9\u30ed\u30fc\u30e2\u30fc\u30c9\u3092\u8a2d\u5b9a\r\n        sun.setDrawMode(DrawMode.FILL);\r\n        \/\/ \u4f4d\u7f6e\u521d\u671f\u5316\r\n        sun.setTranslateX(DISTANCE_SUN);\r\n\r\n        \/\/ \u900f\u8996\u6295\u5f71\u30ab\u30e1\u30e9\r\n        final PerspectiveCamera cam = new PerspectiveCamera(true);\r\n        \/\/ Field of View \r\n        cam.setFieldOfView(45.5d);\r\n        \/\/ Clipping Planes\r\n        cam.setNearClip(1.0d);\r\n        cam.setFarClip(1_000_000.0d);\r\n        \/\/ \u30ab\u30e1\u30e9\u3092 1500 \u5f8c\u9000\u3055\u305b\u308b\u3002(Z \u8ef8\u3092 -1500)\r\n        cam.setTranslateZ(-1_500.0d);\r\n\r\n        \/\/ \u30a2\u30f3\u30d3\u30a8\u30f3\u30c8\u30e9\u30a4\u30c8\r\n        AmbientLight ambient = new AmbientLight();\r\n        ambient.setColor(Color.rgb(90, 90, 90, 0.6));\r\n\r\n        \/\/ \u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\r\n        PointLight point = new PointLight();\r\n        point.setColor(Color.WHITE);\r\n        point.getScope().addAll(earth, moon);\r\n\r\n        \/\/ \u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u3092\u79fb\u52d5\r\n        point.setTranslateX(DISTANCE_SUN);\r\n\r\n        root.getChildren().addAll(earth, moon, sun, ambient, point);\r\n\r\n        Scene scene = new Scene(root, 1_360, 765, true, SceneAntialiasing.BALANCED);\r\n\r\n        scene.setFill(Color.BLACK);\r\n\r\n        scene.setCamera(cam);\r\n\r\n        \/\/ \u30de\u30a6\u30b9\u3067 pianoGroup \u64cd\u4f5c\u7528\r\n        Rotate xRotate;\r\n        Rotate yRotate;\r\n        Rotate zRotate;\r\n\r\n        root.getTransforms().setAll(\r\n                xRotate = new Rotate(0, Rotate.X_AXIS),\r\n                yRotate = new Rotate(0, Rotate.Y_AXIS),\r\n                zRotate = new Rotate(0, Rotate.Z_AXIS)\r\n        );\r\n\r\n        xRotate.angleProperty().bind(angleX);\r\n        yRotate.angleProperty().bind(angleY);\r\n        zRotate.angleProperty().bind(angleZ);\r\n\r\n        root.setOnMousePressed(event -> {\r\n            anchorX = event.getSceneX();\r\n            anchorY = event.getSceneY();\r\n            anchorAngleX = angleX.get();\r\n            anchorAngleY = angleY.get();\r\n        });\r\n\r\n        root.setOnMouseDragged(event -> {\r\n            angleX.set(anchorAngleX - (anchorY - event.getSceneY()));\r\n            angleY.set(anchorAngleY + anchorX - event.getSceneX());\r\n        });\r\n\r\n        AnimationTimer animation = new AnimationTimer() {\r\n\r\n            \/\/ \u524d\u56de\u6642\u9593\r\n            private long previousHandledTime;\r\n            \/\/ \u89d2\u5ea6\r\n            private double angle;\r\n            \/\/ \u5730\u7403\u306e\u56de\u8ee2\u901f\u5ea6\r\n            private final DoubleProperty earthAngularVelocityProperty = new SimpleDoubleProperty(810.0d);\r\n            \/\/ \u6708\u306e\u56de\u8ee2\u901f\u5ea6\r\n            private final DoubleProperty moonAngularVelocityProperty = new SimpleDoubleProperty(30.0d);\r\n            \/\/ \u6708\u306e\u65b9\u4f4d\u89d2\r\n            private double azimuth;\r\n\r\n            @Override\r\n            public void handle(long now) {\r\n\r\n                if (previousHandledTime == 0) {\r\n                    previousHandledTime = now;\r\n                    return;\r\n                }\r\n\r\n                \/\/ \u5730\u7403\r\n                angle += earthAngularVelocityProperty.get() * (now - previousHandledTime) \/ 1_000_000_000;\r\n                \/\/ \u6708\r\n                azimuth += moonAngularVelocityProperty.get() * (now - previousHandledTime) \/ 1_000_000_000.0d;\r\n\r\n                previousHandledTime = now;\r\n\r\n                \/\/ \u5730\u7403\u3092\uff12\uff13\uff0e\uff15\u5ea6\u50be\u3051\u3066\u81ea\u8ee2\u3055\u305b\u308b\u3002\r\n                earth.getTransforms().setAll(new Rotate(23.5d, Rotate.Z_AXIS), new Rotate(-angle, Rotate.Y_AXIS));\r\n\r\n                \/\/ \u6708\u3092\u56de\u8ee2\u3055\u305b\u308b\u3002\r\n                moon.setTranslateX(Math.sin(Math.toRadians(azimuth)) * DISTANCE_MOON);\r\n                moon.setTranslateZ(-1.0d * Math.cos(Math.toRadians(azimuth)) * DISTANCE_MOON);\r\n                \/\/ \u9905\u3092\u3064\u3044\u3066\u308b\u3046\u3055\u304e\u3092\u5e38\u306b\u5730\u7403\u306b\u5411\u3051\u3066\u56de\u8ee2\u3055\u305b\u308b\u3002\r\n                moon.getTransforms().setAll(new Rotate(-1.0d * azimuth + 180.0d, Rotate.Y_AXIS));\r\n\r\n            }\r\n        };\r\n\r\n        animation.start();\r\n\r\n        primaryStage.setTitle(\"Earth Moon\");\r\n        primaryStage.setScene(scene);\r\n        primaryStage.show();\r\n    }\r\n\r\n    \/**\r\n     * @param args the command line arguments\r\n     *\/\r\n    public static void main(String[] args) {\r\n        launch(args);\r\n    }\r\n\r\n}\r\n\r\n\r\n\r\n<\/pre>\n<\/p>\n<p>\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u306f\u6b21\u306e\u52d5\u753b\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><iframe loading=\"lazy\" height=\"480\" src=\"\/\/www.youtube.com\/embed\/q_BKTOg1tUc?rel=0\" frameborder=\"0\" width=\"640\" allowfullscreen><\/iframe> <\/p>\n<p>&nbsp;<\/p>\n<p>\u3053\u306e\u52d5\u753b\u304b\u3089\u89e3\u308b\u3088\u3046\u306b\u5730\u7403\u3084\u6708\u3067\u592a\u967d\u306e\u5149\uff08\u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\uff09\u304c\u906e\u3089\u308c\u305f\u3068\u304d\u306b\u3067\u304d\u308b\u306f\u305a\u306e\u5f71\u304c\u3067\u304d\u307e\u305b\u3093\u3002<\/p>\n<p>\u5c11\u3057\u6b8b\u5ff5\u306a\u7d50\u679c\u3068\u306a\u308a\u307e\u3057\u305f\u3002<\/p>\n<p>\u3061\u3087\u3063\u3068\u8131\u7dda\u3057\u3066\u3044\u307e\u3044\u307e\u3057\u305f\u304c ToyPiano \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306b\u5fc5\u8981\u306a\u6700\u5f8c\u306e\u6a5f\u80fd\u3092\u305d\u308d\u305d\u308d\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n<p>\u30ab\u30e1\u30e9\u3092\u52d5\u304b\u3059\uff01<\/p>\n<p>\u3053\u308c\u304c\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u3063\u305f\u3089 ToyPiano \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u4f7f\u3063\u3066\u3044\u308b 3D \u95a2\u4fc2\u306e\u6280\u8853\u306f\u5168\u3066\u3042\u306a\u305f\u306e\u3082\u306e\u3067\u3059\u3002<\/p>\n<p>32 \u9375\u76e4\u3068\u307f\u307f\u3063\u3061\u3044\u3053\u3068\u8a00\u308f\u305a\u306b 88 \u9375\u76e4\u306e\u672c\u683c\u7684\u306a 3D Piano \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3060\u3063\u3066\u4f5c\u308c\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002<\/p>\n<p>\u305d\u308c\u3067\u306f\u6b21\u306e\u3088\u3046\u306a\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u7d44\u3093\u3067\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>Cylinder \u3092\u624b\u524d\u306b\uff14\uff15\u5ea6\u50be\u3051\u3066\u3001\u30d4\u30dc\u30c3\u30c8\u306f\u6700\u4e0b\u90e8\u3067\u4e00\u756a\u624b\u524d\u306e\u4f4d\u7f6e\u3068\u3057\u3066\u8868\u793a\u3055\u305b\u308b\u3002<\/p>\n<p>\u3053\u308c\u306f\u4eca\u307e\u3067\u306e\u8a18\u4e8b\u306e\u4e2d\u3067\u7c21\u5358\u306b\u3067\u304d\u308b\u3053\u3068\u304c\u8a3c\u660e\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>\u30c8\u30b0\u30eb\u30dc\u30bf\u30f3\u3092\u9069\u5f53\u306b\u914d\u7f6e\u3057\u3066\u3001\u30dc\u30bf\u30f3\u304c\u62bc\u3055\u308c\u305f\u3089\u30ab\u30e1\u30e9\u3092 Cylinder \u3092\u4e2d\u5fc3\u306b\u6c34\u5e73\u306b\u56de\u8ee2\u3055\u305b\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>\u3082\u3061\u308d\u3093\u30ab\u30e1\u30e9\u306f\u5e38\u306b Cylinder \u306b\u5411\u3044\u3066\u307e\u3059\u3002<\/p>\n<p>\u3053\u308c\u3092\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u8868\u793a\u3055\u3066\u307e\u3059\u3002<\/p>\n<p>\u30c8\u30b0\u30eb\u30dc\u30bf\u30f3\u3092\u518d\u5ea6\u62bc\u3057\u3066\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u3092\u6b62\u3081\u3066\u521d\u671f\u72b6\u614b\u306b\u623b\u3057\u307e\u3059\u3002<\/p>\n<p>\u3053\u306e\u8a18\u4e8b\u3092\u3053\u3053\u307e\u3067\u8aad\u3093\u3067\u304f\u3060\u3055\u3063\u305f\u65b9\u306f X, Z \u8ef8\u306e\u4f4d\u7f6e\u3092\u8a08\u7b97\u3057\u3066\u79fb\u52d5\u3055\u305b\u3066\u3001\u30ab\u30e1\u30e9\u304c Cylinder \u306e\u4e2d\u5fc3\u306b\u5411\u304b\u3046\u3088\u3046\u306b<\/p>\n<p>Y \u8ef8\u3092\u56de\u8ee2\u3055\u305b\u308c\u3070\u3044\u3044\u3060\u3051\u3058\u3083\u3093\u3002\u3063\u3066\u601d\u3063\u305f\u3067\u3057\u3087\u3046\u3002<\/p>\n<p>\u304a\u305d\u3089\u304f\u591a\u304f\u306e\u65b9\u306f\u6b21\u306e\u3088\u3046\u306a\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u601d\u3044\u3064\u304f\u306e\u3067\u306f\u306a\u3044\u304b\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n<p><pre title=\"JavaFX3D_Camera.java\">\r\npackage jp.yucchi.javafx3d_camera;\r\n\r\nimport javafx.animation.AnimationTimer;\r\nimport javafx.application.Application;\r\nimport javafx.scene.AmbientLight;\r\nimport javafx.scene.Group;\r\nimport javafx.scene.PerspectiveCamera;\r\nimport javafx.scene.PointLight;\r\nimport javafx.scene.Scene;\r\nimport javafx.scene.SceneAntialiasing;\r\nimport javafx.scene.control.ToggleButton;\r\nimport javafx.scene.image.Image;\r\nimport javafx.scene.layout.GridPane;\r\nimport javafx.scene.paint.Color;\r\nimport javafx.scene.paint.PhongMaterial;\r\nimport javafx.scene.shape.Cylinder;\r\nimport javafx.scene.transform.Rotate;\r\nimport javafx.stage.Stage;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic class JavaFX3D_Camera extends Application {\r\n\r\n    \/\/ \u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u30bf\u30a4\u30de\u30fc\r\n    private AnimationTimer anim;\r\n\r\n    @Override\r\n    public void start(Stage primaryStage) {\r\n\r\n        final Group root = new Group();\r\n\r\n        \/\/ Cylinder\r\n        final Cylinder cylinder = new Cylinder(100.0d, 400.0d);\r\n\r\n        \/\/ Cylinder \u3092\u624b\u524d\u306b\uff14\uff15\u5ea6\u50be\u3051\u308b\u3002\u30d4\u30dc\u30c3\u30c8\u306f\u6700\u4e0b\u90e8\u3067\u4e00\u756a\u624b\u524d\u306e\u4f4d\u7f6e\u3068\u3059\u308b\r\n        cylinder.getTransforms().setAll(new Rotate(45.0d, 0.0d, 200.0d, -100.0d, Rotate.X_AXIS));\r\n\r\n        \/\/ \u30d5\u30a9\u30f3\u30b7\u30a7\u30fc\u30c7\u30a3\u30f3\u30b0\u3092\u8a2d\u5b9a\r\n        final PhongMaterial material = new PhongMaterial();\r\n        \/\/ \u30c6\u30af\u30b9\u30c1\u30e3\u3092\u8cbc\u308b\u3002\r\n        Image diffuseMap = new Image(this.getClass().getResource(\"resources\/Duke.jpg\").toExternalForm());\r\n        material.setDiffuseMap(diffuseMap);\r\n        cylinder.setMaterial(material);\r\n        material.setDiffuseColor(Color.GHOSTWHITE);\r\n        material.setSpecularColor(Color.WHITE);\r\n        cylinder.setMaterial(material);\r\n\r\n        \/\/ \u74b0\u5883\u5149\u8a2d\u5b9a\r\n        final AmbientLight ambient = new AmbientLight();\r\n        ambient.setColor(Color.rgb(90, 90, 90, 0.6));\r\n        ambient.getScope().addAll(cylinder);\r\n\r\n        \/\/ \u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u8a2d\u5b9a\r\n        PointLight point = new PointLight();\r\n        point.setColor(Color.BLUE);\r\n        point.setLayoutX(-500.0d);\r\n        point.setLayoutY(0.0d);\r\n        point.setTranslateZ(0.0d);\r\n        point.getScope().addAll(cylinder);\r\n\r\n        PointLight point2 = new PointLight();\r\n        point2.setColor(Color.RED);\r\n        point2.setLayoutX(500.0d);\r\n        point2.setLayoutY(0.0d);\r\n        point2.setTranslateZ(0.0d);\r\n        point2.getScope().addAll(cylinder);\r\n\r\n        PointLight point3 = new PointLight();\r\n        point3.setColor(Color.WHITE);\r\n        point3.setLayoutX(0.0d);\r\n        point3.setLayoutY(0.0d);\r\n        point3.setTranslateZ(-500.0d);\r\n        point3.getScope().addAll(cylinder);\r\n\r\n        \/\/ \u56db\u3064\u76ee\u306e\u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u52b9\u679c\u7121\u3057(>_<\uff61)\r\n        PointLight point4 = new PointLight();\r\n        point4.setColor(Color.WHITE);\r\n        point4.setLayoutX(0.0d);\r\n        point4.setLayoutY(0.0d);\r\n        point4.setTranslateZ(500.0d);\r\n        point4.getScope().addAll(cylinder);\r\n\r\n        \/\/ \u900f\u8996\u6295\u5f71\u30ab\u30e1\u30e9\r\n        final PerspectiveCamera cam = new PerspectiveCamera(true);\r\n        \/\/ Field of View \r\n        cam.setFieldOfView(45.5d);\r\n        \/\/ Clipping Planes\r\n        cam.setNearClip(1.0d);\r\n        cam.setFarClip(1_000_000.0d);\r\n\r\n        \/\/ \u30ab\u30e1\u30e9\u3092 1000 \u5f8c\u9000\u3055\u305b\u308b\u3002(Z \u8ef8\u3092 -1000)\r\n        cam.setTranslateZ(-1_000.0d);\r\n\r\n        \/\/ \u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u958b\u59cb\u3001\u7d42\u4e86\uff08\u30ea\u30bb\u30c3\u30c8\uff09\u30c8\u30b0\u30eb\u30dc\u30bf\u30f3\r\n        ToggleButton moveCameraButton = new ToggleButton(\"Horizontal rotation\");\r\n        moveCameraButton.setPrefSize(300.0d, 25.0d);\r\n\r\n        GridPane grid = new GridPane();\r\n        grid.add(moveCameraButton, 0, 0, 1, 1);\r\n\t\/\/ \u539f\u70b9\u304c\u4e2d\u592e\u306e\u70ba\u3001\u751f\u8089\u3001\u713c\u8089\u3001\u82e6\u8089\u306e\u51e6\u7406\r\n        grid.setLayoutY(-768.0d \/ 2.0d - 25.0d);\r\n        grid.setLayoutX(1024.0d \/ 2.0d - 300.0d);\r\n\r\n        moveCameraButton.setOnAction(ae -> {\r\n            if (moveCameraButton.isSelected()) {\r\n                moveCameraButton.setText(\"Reset\");\r\n\r\n                anim = new AnimationTimer() {\r\n\r\n                    \/\/ \u30ab\u30e1\u30e9\u7528\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\r\n                    \/\/ \u65b9\u4f4d\u89d2\r\n                    private double azimuth;\r\n                    \/\/ \u524d\u56de\u6642\u9593\r\n                    private long previousHandledTime;\r\n                    \/\/ \u56de\u8ee2\u901f\u5ea6\r\n                    private final double angularVelocity = 15.0d;\r\n                    \/\/ \u534a\u5f84\r\n                    private final double radius = 1_000.0d;\r\n\r\n                    @Override\r\n                    public void handle(long now) {\r\n\r\n                        if (previousHandledTime == 0) {\r\n                            previousHandledTime = now;\r\n                            return;\r\n                        }\r\n\r\n                        \/\/ \u6c34\u5e73\u56de\u8ee2\u51e6\u7406\r\n                        azimuth += angularVelocity * (now - previousHandledTime) \/ 1_000_000_000;\r\n                        previousHandledTime = now;\r\n                        cam.setTranslateX(Math.sin(Math.toRadians(azimuth)) * radius);\r\n                        cam.setTranslateZ(-1.0d * Math.cos(Math.toRadians(azimuth)) * radius);\r\n                        cam.getTransforms().setAll(new Rotate(-1 * azimuth, Rotate.Y_AXIS));\r\n\r\n                    }\r\n                };\r\n\r\n                anim.start();\r\n\r\n            } else {\r\n                \/\/ \u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u30b9\u30c8\u30c3\u30d7\u3001\u30ea\u30bb\u30c3\u30c8\r\n                anim.stop();\r\n                moveCameraButton.setText(\"Horizontal rotation\");\r\n                cam.setTranslateX(0.0d);\r\n                cam.setTranslateZ(-1000.0d);\r\n                cam.getTransforms().setAll(new Rotate(0.0d, 0.0d, 0.0d));\r\n            }\r\n        });\r\n\r\n        root.getChildren().addAll(cylinder, ambient, point, point2, point3, point4, grid);\r\n\r\n        Scene scene = new Scene(root, 1_024, 768, true, SceneAntialiasing.BALANCED);\r\n        scene.setFill(Color.ALICEBLUE);\r\n        scene.setCamera(cam);\r\n\r\n        primaryStage.setTitle(\"JavaFX 3D Camera\");\r\n        primaryStage.setScene(scene);\r\n        primaryStage.show();\r\n    }\r\n\r\n    \/**\r\n     * @param args the command line arguments\r\n     *\/\r\n    public static void main(String[] args) {\r\n        launch(args);\r\n    }\r\n\r\n}\r\n\r\n\r\n\r\n<\/pre>\n<\/p>\n<p>\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/20.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"20\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"20\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/20_thumb.png\" width=\"619\" height=\"484\"><\/a><\/p>\n<p>\u306a\u3093\u304b\u3068\u3093\u3067\u3082\u306a\u3044\u3053\u3068\u306b\u306a\u3063\u3066\u307e\u3059\u306d\u3002<\/p>\n<p>\u52d5\u753b\u306f\u3053\u3061\u3089\u3067\u3059\u3002<\/p>\n<p><iframe loading=\"lazy\" height=\"480\" src=\"\/\/www.youtube.com\/embed\/swXyBrbOr6c?rel=0\" frameborder=\"0\" width=\"640\" allowfullscreen><\/iframe> <\/p>\n<p>\u30ab\u30e1\u30e9\u3092\u52d5\u304b\u3059\u3068\u30c8\u30b0\u30eb\u30dc\u30bf\u30f3\u3082\u5e73\u3079\u3063\u305f\u3044\u5e73\u9762\u4e0a\u306b\u914d\u7f6e\u3055\u308c\u3066\u3044\u308b\u72b6\u614b\u306a\u306e\u304c\u78ba\u8a8d\u3055\u308c\u307e\u3057\u305f\u3002<\/p>\n<p>\u3061\u3087\u3063\u3068\u3053\u308c\u306f\u307e\u305a\u3044\u3067\u3059\u3002<\/p>\n<p>\u30c8\u30b0\u30eb\u30dc\u30bf\u30f3\u304c\u62bc\u3057\u306b\u304f\u3044\u3058\u3083\u3042\u308a\u307e\u305b\u3093\u304b\uff01\uff08\u305d\u3053\u304b\uff01\uff1f<\/p>\n<p>\u3061\u306a\u307f\u306b\u3053\u306e\u30c8\u30b0\u30eb\u30dc\u30bf\u30f3\u306f\u3061\u3083\u3093\u3068\u6a5f\u80fd\u3057\u307e\u3059\u3002(^_^;)<\/p>\n<p>\u7279\u306b\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u8aac\u660e\u3059\u308b\u3068\u3053\u308d\u306f\u7121\u3044\u306e\u3067\u3059\u304c\u3001\u4f55\u6545\u304b\u56db\u3064\u76ee\u306e\u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u304c\u52b9\u304d\u307e\u305b\u3093\u3002<\/p>\n<p>\u30ab\u30e1\u30e9\u304c\u56de\u8ee2\u3057\u3066\u3044\u308b\u3053\u3068\u3092\u89e3\u308a\u3084\u3059\u304f\u3059\u308b\u305f\u3081\u306b\u56db\u65b9\u304b\u3089 PointLight \u3092\u5f53\u3066\u3088\u3046\u3068\u3057\u305f\u306e\u3067\u3059\u304c\u30fb\u30fb\u30fb<\/p>\n<p>PointLight \u306e\u4ef6\u306f\u3061\u3087\u3063\u3068\u89e3\u3089\u306a\u3044\u306e\u3067\u6df1\u304f\u8ffd\u6c42\u305b\u305a\u306b\u809d\u5fc3\u306e\u554f\u984c\u306b\u79fb\u308a\u307e\u3059\u3002(\uffe3\u3002\uffe3;)<\/p>\n<p>\u3053\u306e\u3088\u3046\u306b UI \u7528\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\uff08\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb\uff09\u306a\u3069\u3092\u4eca\u307e\u3067\u901a\u308a\u306b\u64ae\u3057\u3066\u30013D \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u64ae\u3059\u5834\u5408\u306b\u5f71\u97ff\u3092\u53ca\u307c\u3055\u306a\u3044\u3088\u3046\u306b\u3059\u308b\u306b\u306f\u3069\u3046\u3059\u308c\u3070\u3044\u3044\u306e\u304b\uff1f<\/p>\n<p>\u5b9f\u306f\u3053\u306e\u554f\u984c\u3092\u7c21\u5358\u306b\u89e3\u6c7a\u3059\u308b\u305f\u3081\u306b\u7279\u5225\u306a Node \u304c\u7528\u610f\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>javafx.scene.SubScene \u3067\u3059\u3002<\/p>\n<p>\u3053\u308c\u3092\u4f7f\u3063\u3066\u4eca\u307e\u3067\u306e 2D \u7528\u3068 3D \u7528\u3092\u5206\u96e2\u3055\u305b\u3066\u3057\u307e\u3044\u307e\u3059\u3002<\/p>\n<p>\u30ab\u30e1\u30e9\u3082 3D \u7528\u306b( SubScene \u7528 ) \u5225\u306b\u4e00\u3064\u3060\u3051\u7279\u5225\u306b\u7528\u610f\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>\u305d\u308c\u3067\u306f\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3092 SubScene \u3092\u4f7f\u3063\u3066\u671f\u5f85\u901a\u308a\u306b\u52d5\u304f\u3088\u3046\u306b\u3057\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>\u5148\u307b\u3069\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3068\u898b\u305f\u76ee\u306f\u9055\u3046\u3051\u3069\u3084\u3063\u3066\u308b\u3053\u3068\u306f\u540c\u3058\u3067\u3059\u3002<\/p>\n<p>\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb\u306e\u914d\u7f6e\u304c\u3053\u308c\u3067\u81ea\u5728\u306b\u3067\u304d\u308b\u306e\u3067\u5148\u307b\u3069\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3068\u3053\u306e\u90e8\u5206\u306f\u968f\u5206\u9055\u3063\u3066\u307e\u3059\u3002<\/p>\n<p>\u307e\u305f\u3001Scene \u7528\u306e\u30ab\u30e1\u30e9\u304c\u5b9a\u7fa9\u3055\u308c\u3066\u306a\u3044\u306e\u3067\u3059\u304c\u5fc3\u914d\u306b\u306f\u53ca\u3073\u307e\u305b\u3093\u3002<\/p>\n<p>\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30ab\u30e1\u30e9\u304c\u5229\u7528\u3055\u308c\u3066\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb\u306f\u8868\u793a\u3055\u308c\u307e\u3059\u3002<\/p>\n<p>Cylinder \u3092\u64ae\u3059\u305f\u3081\u306b\u56de\u8ee2\u3057\u3066\u3044\u308b\u30ab\u30e1\u30e9\u306f SubScene \u306b\u8a2d\u5b9a\u3055\u308c\u305f\u5c02\u7528\u306e\u30ab\u30e1\u30e9\u306a\u306e\u3067\u5148\u307b\u3069\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u3088\u3046\u306b UI (\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb)\u307e\u3067\u64ae\u3057\u307e\u305b\u3093\u3002<\/p>\n<p>\u5b9f\u306b\u5408\u7406\u7684\u306b\u3053\u306e\u554f\u984c\u3092\u89e3\u6c7a\u3057\u3066\u3044\u307e\u3059\u306d\u3002<\/p>\n<p>\u305d\u308c\u3067\u306f SubScene \u3092\u4f7f\u3063\u3066\u6539\u5584\u3055\u308c\u305f\u30d7\u30ed\u30b0\u30e9\u30e0\u898b\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p><pre title=\"JavaFX3D_Camera.java\">\r\npackage jp.yucchi.javafx3d_camera;\r\n\r\nimport javafx.animation.AnimationTimer;\r\nimport javafx.application.Application;\r\nimport javafx.scene.AmbientLight;\r\nimport javafx.scene.Group;\r\nimport javafx.scene.Parent;\r\nimport javafx.scene.PerspectiveCamera;\r\nimport javafx.scene.PointLight;\r\nimport javafx.scene.Scene;\r\nimport javafx.scene.SceneAntialiasing;\r\nimport javafx.scene.SubScene;\r\nimport javafx.scene.control.ToggleButton;\r\nimport javafx.scene.image.Image;\r\nimport javafx.scene.layout.AnchorPane;\r\nimport javafx.scene.layout.GridPane;\r\nimport javafx.scene.paint.Color;\r\nimport javafx.scene.paint.PhongMaterial;\r\nimport javafx.scene.shape.Cylinder;\r\nimport javafx.scene.transform.Rotate;\r\nimport javafx.stage.Stage;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic class JavaFX3D_Camera extends Application {\r\n\r\n    \/\/ \u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u30bf\u30a4\u30de\u30fc\r\n    private AnimationTimer anim;\r\n    \/\/ \u900f\u8996\u6295\u5f71\u30ab\u30e1\u30e9\r\n    private PerspectiveCamera subCam;\r\n\r\n    @Override\r\n    public void start(Stage primaryStage) {\r\n\r\n        \/\/ SubScene\r\n        final SubScene subScene = createSubScene();\r\n\r\n        \/\/ UI \u30b3\u30f3\u30c8\u30ed\u30fc\u30eb\u7528\r\n        final Parent controlScene = createControlScene();\r\n\r\n        \/\/ UI \u30b3\u30f3\u30c8\u30ed\u30fc\u30eb\u914d\u7f6e\u7528\r\n        final AnchorPane root = new AnchorPane();\r\n        AnchorPane.setRightAnchor(controlScene, 10.0d);\r\n        AnchorPane.setTopAnchor(controlScene, 10.0d);\r\n\r\n        root.getChildren().addAll(subScene, controlScene);\r\n\r\n        final Scene scene = new Scene(root, 1_024, 768, true);\r\n\r\n        primaryStage.setTitle(\"JavaFX 3D Camera\");\r\n        primaryStage.setScene(scene);\r\n        primaryStage.show();\r\n    }\r\n\r\n    \/**\r\n     * @param args the command line arguments\r\n     *\/\r\n    public static void main(String[] args) {\r\n        launch(args);\r\n    }\r\n\r\n    private SubScene createSubScene() {\r\n\r\n        \/\/ SubScene \u7528\u30b0\u30eb\u30fc\u30d7\r\n        final Group subGroup = new Group();\r\n\r\n        \/\/ Cylinder\r\n        final Cylinder cylinder = new Cylinder(100.0d, 400.0d);\r\n\r\n        \/\/ Cylinder \u3092\u624b\u524d\u306b\uff14\uff15\u5ea6\u50be\u3051\u308b\u3002\u30d4\u30dc\u30c3\u30c8\u306f\u6700\u4e0b\u90e8\u3067\u4e00\u756a\u624b\u524d\u306e\u4f4d\u7f6e\u3068\u3059\u308b\r\n        cylinder.getTransforms().setAll(new Rotate(45.0d, 0.0d, 200.0d, -100.0d, Rotate.X_AXIS));\r\n\r\n        \/\/ \u30d5\u30a9\u30f3\u30b7\u30a7\u30fc\u30c7\u30a3\u30f3\u30b0\u3092\u8a2d\u5b9a\r\n        final PhongMaterial material = new PhongMaterial();\r\n        \/\/ \u30c6\u30af\u30b9\u30c1\u30e3\u3092\u8cbc\u308b\u3002\r\n        Image diffuseMap = new Image(this.getClass().getResource(\"resources\/Duke.jpg\").toExternalForm());\r\n        material.setDiffuseMap(diffuseMap);\r\n        cylinder.setMaterial(material);\r\n        material.setDiffuseColor(Color.GHOSTWHITE);\r\n        material.setSpecularColor(Color.WHITE);\r\n        cylinder.setMaterial(material);\r\n\r\n        \/\/ \u74b0\u5883\u5149\u8a2d\u5b9a\r\n        final AmbientLight ambient = new AmbientLight();\r\n        ambient.setColor(Color.rgb(90, 90, 90, 0.6));\r\n        ambient.getScope().addAll(cylinder);\r\n\r\n        \/\/ \u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u8a2d\u5b9a\r\n        PointLight point = new PointLight();\r\n        point.setColor(Color.BLUE);\r\n        point.setLayoutX(-500.0d);\r\n        point.setLayoutY(0.0d);\r\n        point.setTranslateZ(0.0d);\r\n        point.getScope().addAll(cylinder);\r\n\r\n        PointLight point2 = new PointLight();\r\n        point2.setColor(Color.RED);\r\n        point2.setLayoutX(500.0d);\r\n        point2.setLayoutY(0.0d);\r\n        point2.setTranslateZ(0.0d);\r\n        point2.getScope().addAll(cylinder);\r\n\r\n        PointLight point3 = new PointLight();\r\n        point3.setColor(Color.WHITE);\r\n        point3.setLayoutX(0.0d);\r\n        point3.setLayoutY(0.0d);\r\n        point3.setTranslateZ(-500.0d);\r\n        point3.getScope().addAll(cylinder);\r\n\r\n        \/\/ \u56db\u3064\u76ee\u306e\u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u52b9\u679c\u7121\u3057(>_<\uff61)\r\n        PointLight point4 = new PointLight();\r\n        point4.setColor(Color.WHITE);\r\n        point4.setLayoutX(0.0d);\r\n        point4.setLayoutY(0.0d);\r\n        point4.setTranslateZ(500.0d);\r\n        point4.getScope().addAll(cylinder);\r\n\r\n        \/\/ \u900f\u8996\u6295\u5f71\u30ab\u30e1\u30e9\r\n        subCam = new PerspectiveCamera(true);\r\n        \/\/ Field of View \r\n        subCam.setFieldOfView(45.5d);\r\n        \/\/ Clipping Planes\r\n        subCam.setNearClip(1.0d);\r\n        subCam.setFarClip(1_000_000.0d);\r\n\r\n        \/\/ \u30ab\u30e1\u30e9\u3092 1000 \u5f8c\u9000\u3055\u305b\u308b\u3002(Z \u8ef8\u3092 -1000)\r\n        subCam.setTranslateZ(-1_000.0d);\r\n\r\n        subGroup.getChildren().addAll(cylinder, ambient, point, point2, point3, point4);\r\n\r\n        SubScene subScene = new SubScene(subGroup, 1_024, 768, true, SceneAntialiasing.BALANCED);\r\n        subScene.setFill(Color.ALICEBLUE);\r\n        subScene.setCamera(subCam);\r\n\r\n        return subScene;\r\n\r\n    }\r\n\r\n    private Parent createControlScene() {\r\n\r\n        \/\/ \u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u958b\u59cb\u3001\u7d42\u4e86\uff08\u30ea\u30bb\u30c3\u30c8\uff09\u30c8\u30b0\u30eb\u30dc\u30bf\u30f3\r\n        ToggleButton moveCameraButton = new ToggleButton(\"Horizontal rotation\");\r\n        moveCameraButton.setPrefSize(300.0d, 25.0d);\r\n\r\n        GridPane grid = new GridPane();\r\n        grid.add(moveCameraButton, 0, 0, 1, 1);\r\n\r\n        moveCameraButton.setOnAction(ae -> {\r\n            if (moveCameraButton.isSelected()) {\r\n                moveCameraButton.setText(\"Reset\");\r\n\r\n                anim = new AnimationTimer() {\r\n\r\n                    \/\/ \u30ab\u30e1\u30e9\u7528\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\r\n                    \/\/ \u65b9\u4f4d\u89d2\r\n                    private double azimuth;\r\n                    \/\/ \u524d\u56de\u6642\u9593\r\n                    private long previousHandledTime;\r\n                    \/\/ \u56de\u8ee2\u901f\u5ea6\r\n                    private final double angularVelocity = 15.0d;\r\n                    \/\/ \u534a\u5f84\r\n                    private final double radius = 1_000.0d;\r\n\r\n                    @Override\r\n                    public void handle(long now) {\r\n\r\n                        if (previousHandledTime == 0) {\r\n                            previousHandledTime = now;\r\n                            return;\r\n                        }\r\n\r\n                        \/\/ \u6c34\u5e73\u56de\u8ee2\u51e6\u7406\r\n                        azimuth += angularVelocity * (now - previousHandledTime) \/ 1_000_000_000;\r\n                        previousHandledTime = now;\r\n                        subCam.setTranslateX(Math.sin(Math.toRadians(azimuth)) * radius);\r\n                        subCam.setTranslateZ(-1.0d * Math.cos(Math.toRadians(azimuth)) * radius);\r\n                        subCam.getTransforms().setAll(new Rotate(-1 * azimuth, Rotate.Y_AXIS));\r\n\r\n                    }\r\n                };\r\n\r\n                anim.start();\r\n\r\n            } else {\r\n                \/\/ \u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u30b9\u30c8\u30c3\u30d7\u3001\u30ea\u30bb\u30c3\u30c8\r\n                anim.stop();\r\n                moveCameraButton.setText(\"Horizontal rotation\");\r\n                subCam.setTranslateX(0.0d);\r\n                subCam.setTranslateZ(-1_000.0d);\r\n                subCam.getTransforms().setAll(new Rotate(0.0d, 0.0d, 0.0d));\r\n            }\r\n        });\r\n\r\n        return grid;\r\n\r\n    }\r\n\r\n}\r\n\r\n\r\n<\/pre>\n<\/p>\n<p>SubScene \u3063\u3066\u7c21\u5358\u306b\u4fbf\u5229\u306b\u4f7f\u3048\u307e\u3059\u306d\uff01(^_^)<\/p>\n<p>\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u7d50\u679c\u306f\u6b21\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/211.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"21\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"21\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2014\/12\/21_thumb.png\" width=\"624\" height=\"484\"><\/a><\/p>\n<p>&nbsp;<\/p>\n<p><iframe loading=\"lazy\" height=\"480\" src=\"\/\/www.youtube.com\/embed\/paLQGnDkDh0?rel=0\" frameborder=\"0\" width=\"640\" allowfullscreen><\/iframe> <\/p>\n<p>ToyPiano \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u4f5c\u308b\u305f\u3081\u306b\u5fc5\u8981\u306a JavaFX 3D API \u306f\u3053\u308c\u3067\u5168\u3066\u3067\u3059\u3002<\/p>\n<p>JavaFX \u306f\u6a19\u6e96\u3067 3D API \u3092\u6301\u3063\u3066\u3044\u308b\u304b\u3089\u3061\u3087\u3063\u3068\u3057\u305f\u3053\u3068\u306a\u3089\u7c21\u5358\u306b\u4f7f\u3046\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n<p>\u4ed5\u4e8b\u3067\u306f\u4f7f\u3046\u6a5f\u4f1a\u304c\u306a\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u304c\u606f\u629c\u304d\u306b\u904a\u3093\u3067\u307f\u308b\u306e\u3082\u3044\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u306d\u3002(^_^)<\/p>\n<p>\u9577\u304f\u306a\u3063\u3066\u3057\u307e\u3044\u307e\u3059\u304c\u9375\u76e4\u6570\u3092\u6e1b\u3089\u3057\u305f\u5b8c\u6210\u7248\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u8f09\u305b\u3066\u304a\u304d\u307e\u3059\u3002<\/p>\n<p>\u79c1\u306f\u30b9\u30fc\u30d1\u30fc\u30b5\u30a4\u30e4\u4eba\u4e26\u306e\u7d20\u4eba\u306a\u306e\u3067\u3044\u3064\u3082\u306a\u304c\u3089\u6c5a\u3044\u30b3\u30fc\u30c9\u3067\u3059\u304c\u53c2\u8003\u306b\u306a\u308c\u3070\u5e78\u3044\u3067\u3059\u3002<\/p>\n<p>\u9593\u9055\u3044\u3001\u30a2\u30c9\u30d0\u30a4\u30b9\u7b49\u306f\u5927\u6b53\u8fce\u3067\u3059\u306e\u3067\u304a\u6c17\u4ed8\u304d\u306e\u70b9\u304c\u3042\u308c\u3070\u3054\u6559\u793a\u304f\u3060\u3055\u3044\u307e\u305b\u3002<\/p>\n<p><pre title=\"PressedAction.java\">\r\npackage jp.yucchi.toypiano;\r\n\r\nimport javafx.scene.media.AudioClip;\r\nimport javafx.scene.shape.Box;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic interface PressedAction {\r\n    \r\n    double WHITE_KEYBOARD_DOWN_ANGLE = 4.0d;\r\n    \r\n    double BLACK_KEYBOARD_DOWN_ANGLE = 5.5d;\r\n\r\n    void pressedWhiteKeyBoard(AudioClip ac, Box keyBoard, double keyBoardDepth);\r\n    \r\n    void pressedBlackKeyBoard(AudioClip ac, Box keyBoard, double keyBoardDepth);\r\n\r\n}\r\n\r\n<\/pre>\n<\/p>\n<p><pre title=\"ReleasedAction.java\">\r\n\r\npackage jp.yucchi.toypiano;\r\n\r\nimport javafx.scene.shape.Box;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic interface ReleasedAction {\r\n\r\n    void releasedKeyBoard(Box keyBoard);\r\n\r\n}\r\n\r\n\r\n<\/pre>\n<\/p>\n<p><pre title=\"Recording.java\">\r\n\r\npackage jp.yucchi.toypiano;\r\n\r\nimport java.util.List;\r\nimport javafx.scene.input.TouchEvent;\r\nimport javafx.scene.shape.Box;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic interface Recording {\r\n\r\n    void recordingEvent(boolean recording, List<EventRecording> eventRecording, long actionEventTime, Box keyboard, TouchEvent te);\r\n}\r\n\r\n\r\n<\/pre>\n<\/p>\n<p><pre title=\"PianoAction.java\">\r\n\r\npackage jp.yucchi.toypiano;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic interface PianoAction extends PressedAction, ReleasedAction, Recording {\r\n\r\n    \/\/ \u767d\u3055\u304c\u7729\u3057\u3044\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30fc\u30b9\r\n    \r\n}\r\n\r\n\r\n<\/pre>\n<\/p>\n<p><pre title=\"EventRecording.java\">\r\npackage jp.yucchi.toypiano;\r\n\r\nimport java.io.Serializable;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic class EventRecording implements Serializable {\r\n    \r\n    private static final long serialVersionUID = 1L;\r\n\r\n    private final long eventTime;\r\n    private final String eventProducer;\r\n    private final String eventType;\r\n\r\n    public EventRecording(long eventTime, String eventProducer, String eventType) {\r\n        this.eventTime = eventTime;\r\n        this.eventProducer = eventProducer;\r\n        this.eventType = eventType;\r\n    }\r\n\r\n    public long getEventTime() {\r\n        return eventTime;\r\n    }\r\n\r\n    public String getEventProducer() {\r\n        return eventProducer;\r\n    }\r\n\r\n    public String getEventType() {\r\n        return eventType;\r\n    }\r\n\r\n}\r\n\r\n\r\n\r\n<\/pre>\n<\/p>\n<p><pre title=\"ToyPiano.java\">\r\npackage jp.yucchi.toypiano;\r\n\r\nimport java.io.File;\r\nimport java.io.FileInputStream;\r\nimport java.io.FileNotFoundException;\r\nimport java.io.FileOutputStream;\r\nimport java.io.IOException;\r\nimport java.io.ObjectInputStream;\r\nimport java.io.ObjectOutputStream;\r\nimport java.util.ArrayList;\r\nimport java.util.List;\r\nimport java.util.logging.Level;\r\nimport java.util.logging.Logger;\r\nimport javafx.animation.AnimationTimer;\r\nimport javafx.animation.Interpolator;\r\nimport javafx.animation.KeyFrame;\r\nimport javafx.animation.KeyValue;\r\nimport javafx.animation.Timeline;\r\nimport javafx.application.Application;\r\nimport javafx.application.Platform;\r\nimport javafx.beans.property.DoubleProperty;\r\nimport javafx.beans.property.SimpleDoubleProperty;\r\nimport javafx.geometry.HPos;\r\nimport javafx.scene.AmbientLight;\r\nimport javafx.scene.Cursor;\r\nimport javafx.scene.Group;\r\nimport javafx.scene.Node;\r\nimport javafx.scene.Parent;\r\nimport javafx.scene.PerspectiveCamera;\r\nimport javafx.scene.PointLight;\r\nimport javafx.scene.Scene;\r\nimport javafx.scene.SceneAntialiasing;\r\nimport javafx.scene.SubScene;\r\nimport javafx.scene.control.Button;\r\nimport javafx.scene.control.ToggleButton;\r\nimport javafx.scene.image.Image;\r\nimport javafx.scene.input.KeyCode;\r\nimport javafx.scene.input.TouchEvent;\r\nimport javafx.scene.layout.AnchorPane;\r\nimport javafx.scene.layout.GridPane;\r\nimport javafx.scene.layout.Region;\r\nimport javafx.scene.media.AudioClip;\r\nimport javafx.scene.paint.Color;\r\nimport javafx.scene.paint.PhongMaterial;\r\nimport javafx.scene.shape.Box;\r\nimport javafx.scene.shape.DrawMode;\r\nimport javafx.scene.transform.Rotate;\r\nimport javafx.stage.FileChooser;\r\nimport javafx.stage.Stage;\r\nimport javafx.util.Duration;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic class ToyPiano extends Application implements PianoAction {\r\n\r\n    \/\/ \u30d4\u30a2\u30ce\r\n    private Group pianoGroup;\r\n\r\n    \/\/ \u30d4\u30a2\u30ce\u30dd\u30b8\u30b7\u30e7\u30f3\r\n    private final DoubleProperty pxPos = new SimpleDoubleProperty(0.0d);\r\n    private final DoubleProperty pyPos = new SimpleDoubleProperty(0.0d);\r\n    private final DoubleProperty pzPos = new SimpleDoubleProperty(0.0d);\r\n\r\n    \/\/ \u30b5\u30d6\u30ab\u30e1\u30e9\r\n    private PerspectiveCamera subCam;\r\n\r\n    \/\/ \u30b5\u30d6\u30ab\u30e1\u30e9\u79fb\u52d5\r\n    private final DoubleProperty xPos = new SimpleDoubleProperty(0.0d);\r\n    private final DoubleProperty yPos = new SimpleDoubleProperty(0.0d);\r\n    private final DoubleProperty zPos = new SimpleDoubleProperty(-600.0d);\r\n\r\n    \/\/ \u30b5\u30d6\u30ab\u30e1\u30e9\u56de\u8ee2\r\n    private final DoubleProperty rxPos = new SimpleDoubleProperty(0.0d);\r\n    private final DoubleProperty ryPos = new SimpleDoubleProperty(0.0d);\r\n    private final DoubleProperty rzPos = new SimpleDoubleProperty(0.0d);\r\n\r\n    \/\/ \u5ea7\u6a19\r\n    private double anchorAngleX;\r\n    private double anchorAngleY;\r\n    private final DoubleProperty angleX = new SimpleDoubleProperty(0d);\r\n    private final DoubleProperty angleY = new SimpleDoubleProperty(0d);\r\n    private final DoubleProperty angleZ = new SimpleDoubleProperty(0d);\r\n    private double anchorX;\r\n    private double anchorY;\r\n\r\n    private ToggleButton openCloseButton;\r\n\r\n    private Button recordingButton;\r\n\r\n    private Button stopButton;\r\n\r\n    private Button playbackButton;\r\n\r\n    private Button saveButton;\r\n\r\n    private Button loadButton;\r\n\r\n    private FileChooser fileChooser;\r\n\r\n    private Box keyboard_f;\r\n    private Box keyboard_g;\r\n    private Box keyboard_a;\r\n    private Box keyboard_b;\r\n    private Box keyboard_f_s;\r\n    private Box keyboard_g_s;\r\n    private Box keyboard_a_s;\r\n\r\n    private boolean recording;\r\n\r\n    private List<EventRecording> eventRecording;\r\n\r\n    private long actionEventTime;\r\n\r\n    private long recordingLastTime;\r\n\r\n    private AnimationTimer recordingAnimation;\r\n    private AnimationTimer playbackAnimation;\r\n\r\n    private AudioClip f;\r\n    private AudioClip f_s;\r\n    private AudioClip g;\r\n    private AudioClip g_s;\r\n    private AudioClip a;\r\n    private AudioClip a_s;\r\n    private AudioClip b;\r\n    private AudioClip dameyo;\r\n\r\n    private double whiteKeyBoardDepth;\r\n    private double blackKeyBoardDepth;\r\n\r\n    private boolean activePlayback;\r\n\r\n    private int touchPressedCount; \/\/ \u30e9\u30e0\u30c0\u5f0f\u304b\u3089\u30a2\u30af\u30bb\u30b9 \u53d6\u6271\u6ce8\u610f\r\n    private int touchReleasedCount; \/\/ \u30e9\u30e0\u30c0\u5f0f\u304b\u3089\u30a2\u30af\u30bb\u30b9 \u53d6\u6271\u6ce8\u610f\r\n\r\n    private Cursor cursor;\r\n\r\n    @Override\r\n    public void start(Stage primaryStage) {\r\n\r\n        final SubScene subScene = createSubScene();\r\n\r\n        final Parent controlScene = createControlScene();\r\n\r\n        final AnchorPane root = new AnchorPane();\r\n        root.getChildren().addAll(subScene, controlScene);\r\n        AnchorPane.setRightAnchor(controlScene, 0.0d);\r\n\r\n        final Scene scene = new Scene(root, 1_920, 1_080, true);\r\n\r\n        \/\/ \u30d7\u30ec\u30a4\u30d0\u30c3\u30af\u4ee5\u5916\u306e\u30bf\u30c3\u30c1\u30c9\u30e9\u30c3\u30b0\u3092\u7981\u6b62\u3055\u305b\u308b\u305f\u3081\u306b\r\n        subScene.setOnTouchPressed(te -> {\r\n            touchPressedCount++; \/\/ \u30d5\u30a3\u30fc\u30eb\u30c9\u3078\u30a2\u30af\u30bb\u30b9 \u53d6\u6271\u6ce8\u610f\r\n        });\r\n\r\n        subScene.setOnTouchReleased(te -> {\r\n            touchReleasedCount++; \/\/ \u30d5\u30a3\u30fc\u30eb\u30c9\u3078\u30a2\u30af\u30bb\u30b9 \u53d6\u6271\u6ce8\u610f\r\n        });\r\n\r\n        \/\/ \u30de\u30a6\u30b9\u3067 pianoGroup \u64cd\u4f5c\u7528\r\n        Rotate xRotate;\r\n        Rotate yRotate;\r\n        Rotate zRotate;\r\n\r\n        pianoGroup.getTransforms().setAll(\r\n                xRotate = new Rotate(0, Rotate.X_AXIS),\r\n                yRotate = new Rotate(0, Rotate.Y_AXIS),\r\n                zRotate = new Rotate(0, Rotate.Z_AXIS)\r\n        );\r\n\r\n        xRotate.angleProperty().bind(angleX);\r\n        yRotate.angleProperty().bind(angleY);\r\n        zRotate.angleProperty().bind(angleZ);\r\n\r\n        subScene.setOnMousePressed(event -> {\r\n            anchorX = event.getSceneX();\r\n            anchorY = event.getSceneY();\r\n            anchorAngleX = angleX.get();\r\n            anchorAngleY = angleY.get();\r\n        });\r\n\r\n        subScene.setOnMouseDragged(event -> {\r\n            if (touchPressedCount == touchReleasedCount || activePlayback) {\r\n                angleX.set(anchorAngleX - (anchorY - event.getSceneY()));\r\n                angleY.set(anchorAngleY + anchorX - event.getSceneX());\r\n            }\r\n        });\r\n\r\n        pianoGroup.translateXProperty().bindBidirectional(pxPos);\r\n        pianoGroup.translateYProperty().bindBidirectional(pyPos);\r\n        pianoGroup.translateZProperty().bindBidirectional(pzPos);\r\n\r\n        \/\/ ALT + E \u30ad\u30fc\u3067\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u7d42\u4e86\r\n        root.setOnKeyPressed(key -> {\r\n            if (key.getCode() == KeyCode.E && key.isAltDown()) {\r\n                Platform.exit();\r\n                System.exit(0);\r\n            }\r\n        });\r\n\r\n        \/\/ Icon \u8a2d\u5b9a\r\n        Image myIcon = new Image(this.getClass().getResource(\"resources\/sakura_icon.png\").toExternalForm());\r\n        primaryStage.getIcons().add(myIcon);\r\n\r\n        primaryStage.setTitle(\"Java FX ToyPiano\");\r\n        primaryStage.setScene(scene);\r\n        primaryStage.setResizable(false);\r\n        primaryStage.setFullScreen(true);\r\n        primaryStage.setFullScreenExitHint(\"ESC: Full-screen mode end.\" + \"\\nALT + E: Application Exit.\");\r\n        primaryStage.show();\r\n\r\n        \/\/ \u30aa\u30d7\u30b7\u30e7\u30f3\u64cd\u4f5c\u7528 UI \u3092\u9589\u3058\u3066\u304a\u304f\r\n        openCloseButton.fire();\r\n\r\n        \/\/ \u30aa\u30fc\u30d7\u30cb\u30f3\u30b0\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\r\n        openAnimation();\r\n\r\n        \/\/ \u30d5\u30a1\u30a4\u30eb\u30c1\u30e5\u30fc\u30b6\r\n        fileChooser = new FileChooser();\r\n        fileChooser.setInitialDirectory(new File(System.getProperty(\"user.home\")));\r\n        fileChooser.getExtensionFilters()\r\n                .addAll(new FileChooser.ExtensionFilter(\"Piano Files\", \"*.pia\"),\r\n                        new FileChooser.ExtensionFilter(\"All Files\", \"*.*\"));\r\n\r\n    }\r\n\r\n    \/**\r\n     * @param args the command line arguments\r\n     *\/\r\n    public static void main(String[] args) {\r\n        launch(args);\r\n    }\r\n\r\n    private SubScene createSubScene() {\r\n\r\n        \/\/ \u30d4\u30a2\u30ce\u30b0\u30eb\u30fc\u30d7\r\n        pianoGroup = new Group();\r\n\r\n        \/\/ \u30d4\u30a2\u30ce\u306e\u97f3\u6e90\r\n        f = new AudioClip(this.getClass().getResource(\"resources\/F.wav\").toExternalForm());\r\n        f_s = new AudioClip(this.getClass().getResource(\"resources\/F_S.wav\").toExternalForm());\r\n        g = new AudioClip(this.getClass().getResource(\"resources\/G.wav\").toExternalForm());\r\n        g_s = new AudioClip(this.getClass().getResource(\"resources\/G_S.wav\").toExternalForm());\r\n        a = new AudioClip(this.getClass().getResource(\"resources\/A.wav\").toExternalForm());\r\n        a_s = new AudioClip(this.getClass().getResource(\"resources\/A_S.wav\").toExternalForm());\r\n        b = new AudioClip(this.getClass().getResource(\"resources\/B.wav\").toExternalForm());\r\n        dameyo = new AudioClip(this.getClass().getResource(\"resources\/Dameyo.wav\").toExternalForm());\r\n\r\n        \/\/ \u30d4\u30a2\u30ce\r\n        \/\/ \u767d\u9375\u76e4\r\n        final double whiteKeyBoardWidth = 30.0d;\r\n        final double whiteKeyBoardHeight = 30.0d;\r\n        whiteKeyBoardDepth = whiteKeyBoardWidth * 6;\r\n\r\n        \/\/ \u9ed2\u9375\u76e4\r\n        final double blackKeyBoardWidth = whiteKeyBoardWidth * 0.7;\r\n        final double blackKeyBoardHeight = 30.0d;\r\n        blackKeyBoardDepth = whiteKeyBoardDepth * 0.6;\r\n        final double blackKeyBoardGap = whiteKeyBoardWidth * 0.15;\r\n\r\n        \/\/ \u767d\u9375\u76e4\u306e\u9593\u9699\r\n        final double whiteKeyBoardGap = 2.0d;\r\n\r\n        \/\/ \u30dc\u30c7\u30a3\r\n        final double bodyHeight = 50.0d;\r\n        final double bodyDepth = 350.0d;\r\n        final double bodyWidth = whiteKeyBoardWidth * 20 + whiteKeyBoardGap * 18;\r\n\r\n        \/\/ \u767d\u9375\u76e4\u5de6\u7aef\u914d\u7f6e\u958b\u59cb\u4f4d\u7f6e\r\n        final double xStart = -(bodyWidth \/ 2) + whiteKeyBoardWidth;\r\n\r\n        \/\/ \u767d\u9375\u76e4\u306e\u4f4d\u7f6e\u304c\u304c\u30dc\u30c7\u30a3\u3088\u308a\u624b\u524d\u306b\u53ce\u307e\u308b\u3088\u3046\u306b\u30de\u30fc\u30b8\u30f3\u8a2d\u5b9a\r\n        final double depthMargin = 15d;\r\n\r\n        \/\/ \u30dc\u30c7\u30a3 \u30de\u30c6\u30ea\u30a2\u30eb\r\n        final PhongMaterial bodyMaterial = new PhongMaterial();\r\n        bodyMaterial.setDiffuseColor(Color.RED);\r\n        bodyMaterial.setSpecularColor(Color.TOMATO);\r\n\r\n        \/\/ \u767d\u9375\u76e4 \u30de\u30c6\u30ea\u30a2\u30eb\r\n        final PhongMaterial whiteKeyBoardPhongMaterial = new PhongMaterial();\r\n        whiteKeyBoardPhongMaterial.setDiffuseColor(Color.GHOSTWHITE);\r\n        whiteKeyBoardPhongMaterial.setSpecularColor(Color.WHITE);\r\n\r\n        \/\/ \u9ed2\u9375\u76e4 \u30de\u30c6\u30ea\u30a2\u30eb\r\n        final PhongMaterial blackKeyBoardPhongMaterial = new PhongMaterial();\r\n        blackKeyBoardPhongMaterial.setDiffuseColor(Color.DIMGRAY);\r\n        blackKeyBoardPhongMaterial.setSpecularColor(Color.DARKGRAY);\r\n\r\n        final Box body = new Box(bodyWidth, bodyHeight, bodyDepth);\r\n        body.setMaterial(bodyMaterial);\r\n        body.setDrawMode(DrawMode.FILL);\r\n\r\n        final Box body2 = new Box(bodyWidth, bodyHeight, bodyDepth - whiteKeyBoardDepth - depthMargin);\r\n        body2.setMaterial(bodyMaterial);\r\n        body2.setDrawMode(DrawMode.FILL);\r\n        body2.setTranslateY(-bodyHeight);\r\n        body2.setTranslateZ(bodyDepth \/ 2 - (bodyDepth - whiteKeyBoardDepth - depthMargin) \/ 2);\r\n\r\n        keyboard_f = new Box(whiteKeyBoardWidth, whiteKeyBoardHeight, whiteKeyBoardDepth);\r\n        keyboard_f.setUserData(\"F\");\r\n        keyboard_f.setMaterial(whiteKeyBoardPhongMaterial);\r\n        keyboard_f.setDrawMode(DrawMode.FILL);\r\n        keyboard_f.setTranslateX(xStart);\r\n        keyboard_f.setTranslateY(-bodyHeight \/ 2);\r\n        keyboard_f.setTranslateZ(-(bodyDepth \/ 2 - whiteKeyBoardDepth \/ 2) + depthMargin);\r\n\r\n        keyboard_g = new Box(whiteKeyBoardWidth, whiteKeyBoardHeight, whiteKeyBoardDepth);\r\n        keyboard_g.setUserData(\"G\");\r\n        keyboard_g.setMaterial(whiteKeyBoardPhongMaterial);\r\n        keyboard_g.setDrawMode(DrawMode.FILL);\r\n        keyboard_g.setTranslateX(xStart + whiteKeyBoardGap + whiteKeyBoardWidth);\r\n        keyboard_g.setTranslateY(-bodyHeight \/ 2);\r\n        keyboard_g.setTranslateZ(-(bodyDepth \/ 2 - whiteKeyBoardDepth \/ 2) + depthMargin);\r\n\r\n        keyboard_a = new Box(whiteKeyBoardWidth, whiteKeyBoardHeight, whiteKeyBoardDepth);\r\n        keyboard_a.setUserData(\"A\");\r\n        keyboard_a.setMaterial(whiteKeyBoardPhongMaterial);\r\n        keyboard_a.setDrawMode(DrawMode.FILL);\r\n        keyboard_a.setTranslateX(xStart + whiteKeyBoardGap * 2 + whiteKeyBoardWidth * 2);\r\n        keyboard_a.setTranslateY(-bodyHeight \/ 2);\r\n        keyboard_a.setTranslateZ(-(bodyDepth \/ 2 - whiteKeyBoardDepth \/ 2) + depthMargin);\r\n\r\n        keyboard_b = new Box(whiteKeyBoardWidth, whiteKeyBoardHeight, whiteKeyBoardDepth);\r\n        keyboard_b.setUserData(\"B\");\r\n        keyboard_b.setMaterial(whiteKeyBoardPhongMaterial);\r\n        keyboard_b.setDrawMode(DrawMode.FILL);\r\n        keyboard_b.setTranslateX(xStart + whiteKeyBoardGap * 3 + whiteKeyBoardWidth * 3);\r\n        keyboard_b.setTranslateY(-bodyHeight \/ 2);\r\n        keyboard_b.setTranslateZ(-(bodyDepth \/ 2 - whiteKeyBoardDepth \/ 2) + depthMargin);\r\n\r\n        keyboard_f_s = new Box(blackKeyBoardWidth, blackKeyBoardHeight, blackKeyBoardDepth);\r\n        keyboard_f_s.setUserData(\"F_S\");\r\n        keyboard_f_s.setMaterial(blackKeyBoardPhongMaterial);\r\n        keyboard_f_s.setDrawMode(DrawMode.FILL);\r\n        keyboard_f_s.setTranslateX(xStart + whiteKeyBoardWidth \/ 2 + whiteKeyBoardGap \/ 2 - blackKeyBoardGap);\r\n        keyboard_f_s.setTranslateY(-(bodyHeight \/ 2 + whiteKeyBoardHeight \/ 2));\r\n        keyboard_f_s.setTranslateZ(whiteKeyBoardDepth - blackKeyBoardDepth \/ 2 - bodyDepth \/ 2 + depthMargin);\r\n\r\n        keyboard_g_s = new Box(blackKeyBoardWidth, blackKeyBoardHeight, blackKeyBoardDepth);\r\n        keyboard_g_s.setUserData(\"G_S\");\r\n        keyboard_g_s.setMaterial(blackKeyBoardPhongMaterial);\r\n        keyboard_g_s.setDrawMode(DrawMode.FILL);\r\n        keyboard_g_s.setTranslateX(xStart + whiteKeyBoardWidth \/ 2 + whiteKeyBoardGap \/ 2 + whiteKeyBoardWidth + whiteKeyBoardGap);\r\n        keyboard_g_s.setTranslateY(-(bodyHeight \/ 2 + whiteKeyBoardHeight \/ 2));\r\n        keyboard_g_s.setTranslateZ(whiteKeyBoardDepth - blackKeyBoardDepth \/ 2 - bodyDepth \/ 2 + depthMargin);\r\n\r\n        keyboard_a_s = new Box(blackKeyBoardWidth, blackKeyBoardHeight, blackKeyBoardDepth);\r\n        keyboard_a_s.setUserData(\"A_S\");\r\n        keyboard_a_s.setMaterial(blackKeyBoardPhongMaterial);\r\n        keyboard_a_s.setDrawMode(DrawMode.FILL);\r\n        keyboard_a_s.setTranslateX(xStart + whiteKeyBoardWidth \/ 2 + whiteKeyBoardGap \/ 2 + (whiteKeyBoardWidth + whiteKeyBoardGap) * 2 + blackKeyBoardGap);\r\n        keyboard_a_s.setTranslateY(-(bodyHeight \/ 2 + whiteKeyBoardHeight \/ 2));\r\n        keyboard_a_s.setTranslateZ(whiteKeyBoardDepth - blackKeyBoardDepth \/ 2 - bodyDepth \/ 2 + depthMargin);\r\n\r\n        \/\/ \u30d4\u30a2\u30ce \u30a4\u30d9\u30f3\u30c8\u51e6\u7406\r\n        keyboard_f.setOnTouchPressed(te -> {\r\n            recordingEvent(recording, eventRecording, actionEventTime, keyboard_f, te);\r\n            pressedWhiteKeyBoard(f, keyboard_f, whiteKeyBoardDepth);\r\n        });\r\n\r\n        keyboard_f.setOnTouchReleased(te -> {\r\n            recordingEvent(recording, eventRecording, actionEventTime, keyboard_f, te);\r\n            releasedKeyBoard(keyboard_f);\r\n        });\r\n\r\n        keyboard_g.setOnTouchPressed(te -> {\r\n            recordingEvent(recording, eventRecording, actionEventTime, keyboard_g, te);\r\n            pressedWhiteKeyBoard(g, keyboard_g, whiteKeyBoardDepth);\r\n        });\r\n\r\n        keyboard_g.setOnTouchReleased(te -> {\r\n            recordingEvent(recording, eventRecording, actionEventTime, keyboard_g, te);\r\n            releasedKeyBoard(keyboard_g);\r\n        });\r\n\r\n        keyboard_a.setOnTouchPressed(te -> {\r\n            recordingEvent(recording, eventRecording, actionEventTime, keyboard_a, te);\r\n            pressedWhiteKeyBoard(a, keyboard_a, whiteKeyBoardDepth);\r\n        });\r\n\r\n        keyboard_a.setOnTouchReleased(te -> {\r\n            recordingEvent(recording, eventRecording, actionEventTime, keyboard_a, te);\r\n            releasedKeyBoard(keyboard_a);\r\n        });\r\n\r\n        keyboard_b.setOnTouchPressed(te -> {\r\n            recordingEvent(recording, eventRecording, actionEventTime, keyboard_b, te);\r\n            pressedWhiteKeyBoard(b, keyboard_b, whiteKeyBoardDepth);\r\n        });\r\n\r\n        keyboard_b.setOnTouchReleased(te -> {\r\n            recordingEvent(recording, eventRecording, actionEventTime, keyboard_b, te);\r\n            releasedKeyBoard(keyboard_b);\r\n        });\r\n\r\n        keyboard_f_s.setOnTouchPressed(te -> {\r\n            recordingEvent(recording, eventRecording, actionEventTime, keyboard_f_s, te);\r\n            pressedBlackKeyBoard(f_s, keyboard_f_s, blackKeyBoardDepth);\r\n        });\r\n\r\n        keyboard_f_s.setOnTouchReleased(te -> {\r\n            recordingEvent(recording, eventRecording, actionEventTime, keyboard_f_s, te);\r\n            releasedKeyBoard(keyboard_f_s);\r\n        });\r\n\r\n        keyboard_g_s.setOnTouchPressed(te -> {\r\n            recordingEvent(recording, eventRecording, actionEventTime, keyboard_g_s, te);\r\n            pressedBlackKeyBoard(g_s, keyboard_g_s, blackKeyBoardDepth);\r\n        });\r\n\r\n        keyboard_g_s.setOnTouchReleased(te -> {\r\n            recordingEvent(recording, eventRecording, actionEventTime, keyboard_g_s, te);\r\n            releasedKeyBoard(keyboard_g_s);\r\n        });\r\n\r\n        keyboard_a_s.setOnTouchPressed(te -> {\r\n            recordingEvent(recording, eventRecording, actionEventTime, keyboard_a_s, te);\r\n            pressedBlackKeyBoard(g_s, keyboard_a_s, blackKeyBoardDepth);\r\n        });\r\n\r\n        keyboard_a_s.setOnTouchReleased(te -> {\r\n            recordingEvent(recording, eventRecording, actionEventTime, keyboard_a_s, te);\r\n            releasedKeyBoard(keyboard_a_s);\r\n        });\r\n\r\n        pianoGroup.getChildren().addAll(keyboard_f, keyboard_g, keyboard_a, keyboard_b,\r\n                keyboard_f_s, keyboard_g_s, keyboard_a_s,\r\n                body, body2);\r\n\r\n        \/\/ \u30b5\u30d6\u30b7\u30fc\u30f3\u7528\u306e\u30ab\u30e1\u30e9\r\n        subCam = new PerspectiveCamera(true);\r\n        \/\/ Field of View \r\n        subCam.setFieldOfView(45.5);\r\n        \/\/ Clipping Planes\r\n        subCam.setNearClip(1.0);\r\n        subCam.setFarClip(1_000_000);\r\n\r\n        \/\/ \u30b5\u30d6\u30ab\u30e1\u30e9\u64cd\u4f5c\u7528\r\n        \/\/ \u79fb\u52d5   \r\n        subCam.translateXProperty().bind(xPos);\r\n        subCam.translateYProperty().bind(yPos);\r\n        subCam.translateZProperty().bind(zPos);\r\n\r\n        \/\/ \u56de\u8ee2  \u4f7f\u3063\u3066\u306a\u3044\u3051\u3069\u8aac\u660e\u306e\u305f\u3081\r\n        Rotate rxRotate;\r\n        Rotate ryRotate;\r\n        Rotate rzRotate;\r\n        subCam.getTransforms().setAll(\r\n                rxRotate = new Rotate(0, Rotate.X_AXIS),\r\n                ryRotate = new Rotate(0, Rotate.Y_AXIS),\r\n                rzRotate = new Rotate(0, Rotate.Z_AXIS)\r\n        );\r\n        rxRotate.angleProperty().bind(rxPos);\r\n        ryRotate.angleProperty().bind(ryPos);\r\n        rzRotate.angleProperty().bind(rzPos);\r\n\r\n        \/\/ \u74b0\u5883\u5149\u8a2d\u5b9a\r\n        final AmbientLight ambient = new AmbientLight();\r\n        ambient.setColor(Color.rgb(90, 90, 90, 0.6));\r\n        ambient.getScope().addAll(pianoGroup);\r\n\r\n        \/\/ \u30dd\u30a4\u30f3\u30c8\u30e9\u30a4\u30c8\u8a2d\u5b9a\r\n        PointLight point = new PointLight();\r\n        point.setColor(Color.rgb(255, 255, 255, 1.0));\r\n        point.setLayoutX(0);\r\n        point.setLayoutY(-300);\r\n        point.setTranslateZ(-100);\r\n        point.getScope().addAll(pianoGroup);\r\n\r\n        pianoGroup.getChildren().addAll(ambient, point);\r\n\r\n        SubScene subScene = new SubScene(pianoGroup, 1_920, 1_080, true, SceneAntialiasing.BALANCED);\r\n        subScene.setFill(Color.ALICEBLUE);\r\n        subScene.setCamera(subCam);\r\n\r\n        return subScene;\r\n\r\n    }\r\n\r\n    \/\/ \u30d7\u30ec\u30a4\u30d0\u30c3\u30af\u3001\u30d5\u30a1\u30a4\u30eb\u4fdd\u5b58\u306a\u3069\r\n    private Parent createControlScene() {\r\n\r\n        recordingButton = new Button(\"Recording\");\r\n        stopButton = new Button(\"Stop\");\r\n        playbackButton = new Button(\"Playback\");\r\n        saveButton = new Button(\"Save\");\r\n        loadButton = new Button(\"Load\");\r\n        stopButton.setDisable(true);\r\n        playbackButton.setDisable(true);\r\n        saveButton.setDisable(true);\r\n\r\n        recordingButton.setOnAction(ae -> {\r\n            recording = true;\r\n            if (eventRecording != null) {\r\n                eventRecording = null;\r\n            }\r\n            eventRecording = new ArrayList<>();\r\n            recordingButton.setDisable(true);\r\n            stopButton.setDisable(false);\r\n            playbackButton.setDisable(true);\r\n            saveButton.setDisable(true);\r\n            loadButton.setDisable(true);\r\n            resetKeyboard();\r\n            subCamReset();\r\n            openAnimation();\r\n            recording();\r\n        });\r\n\r\n        stopButton.setOnAction(ae -> {\r\n            activePlayback = false;\r\n            stopButton.setDisable(true);\r\n            recordingButton.setDisable(false);\r\n            playbackButton.setDisable(false);\r\n            if (eventRecording != null) {\r\n                saveButton.setDisable(false);\r\n            } else {\r\n                saveButton.setDisable(true);\r\n            }\r\n            saveButton.setDisable(false);\r\n            loadButton.setDisable(false);\r\n            recordingStop();\r\n        });\r\n\r\n        playbackButton.setOnAction(ae -> {\r\n            recording = false;\r\n            activePlayback = true;\r\n            recordingButton.setDisable(true);\r\n            stopButton.setDisable(false);\r\n            playbackButton.setDisable(true);\r\n            saveButton.setDisable(true);\r\n            loadButton.setDisable(true);\r\n            resetKeyboard();\r\n            playBackAnimation();\r\n            playback();\r\n        });\r\n\r\n        saveButton.setOnAction(ae -> {\r\n            if (eventRecording != null) {\r\n                fileChooser.setTitle(\"Save File\");\r\n                File outFile = fileChooser.showSaveDialog(null);\r\n                if (outFile != null) {\r\n                    ObjectOutputStream oos = null;\r\n                    try {\r\n                        oos = new ObjectOutputStream(new FileOutputStream(outFile.getAbsolutePath()));\r\n                    } catch (IOException ex) {\r\n                        Logger.getLogger(ToyPiano.class.getName()).log(Level.SEVERE, null, ex);\r\n                    }\r\n                    try {\r\n                        oos.writeObject(eventRecording);\r\n                    } catch (IOException ex) {\r\n                        Logger.getLogger(ToyPiano.class.getName()).log(Level.SEVERE, null, ex);\r\n                    }\r\n                }\r\n            }\r\n        });\r\n\r\n        loadButton.setOnAction(ae -> {\r\n            fileChooser.setTitle(\"Load File\");\r\n            File inputFile = fileChooser.showOpenDialog(null);\r\n            if (inputFile != null) {\r\n                ObjectInputStream ois = null;\r\n                try {\r\n                    ois = new ObjectInputStream(new FileInputStream(inputFile.getAbsolutePath()));\r\n                } catch (FileNotFoundException ex) {\r\n                    Logger.getLogger(ToyPiano.class.getName()).log(Level.SEVERE, null, ex);\r\n                } catch (IOException ex) {\r\n                    Logger.getLogger(ToyPiano.class.getName()).log(Level.SEVERE, null, ex);\r\n                }\r\n                eventRecording = new ArrayList<>();\r\n                try {\r\n                    eventRecording = (List<EventRecording>) ois.readObject();\r\n                } catch (IOException | ClassNotFoundException ex) {\r\n                    Logger.getLogger(ToyPiano.class.getName()).log(Level.SEVERE, null, ex);\r\n                    \/\/ 8u40 \u3060\u3063\u305f\u3089\u30a8\u30e9\u30fc\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u3060\u305b\u308b\u3093\u3060\u3051\u3069\u306a\u3041\u30fb\u30fb\u30fb\r\n                }\r\n                recordingButton.setDisable(false);\r\n                stopButton.setDisable(true);\r\n                playbackButton.setDisable(false);\r\n                saveButton.setDisable(true);\r\n                loadButton.setDisable(false);\r\n            }\r\n        });\r\n\r\n        \/\/ \u30aa\u30d7\u30b7\u30e7\u30f3\u64cd\u4f5c\u7528 UI\r\n        \/\/ \u30b0\u30ea\u30c3\u30c9\u30da\u30a4\u30f3 \u30b9\u30da\u30fc\u30b5\u30fc\r\n        Region region = new Region();\r\n        region.setId(\"spacer\");\r\n\r\n        openCloseButton = new ToggleButton(\"Close\");\r\n        openCloseButton.setId(\"open-close-toggle-button\");\r\n\r\n        \/\/ \u30de\u30b9\u30b9\u304c\u30db\u30d0\u30fc\u72b6\u614b\u3001\u30af\u30ea\u30c3\u30af\u3057\u305f\u6642\u306b\u30ab\u30fc\u30bd\u30eb\u5f62\u72b6\u5909\u66f4\r\n        changeCursorStyle(openCloseButton);\r\n\r\n        \/\/ \u30b0\u30ea\u30c3\u30c9\u30da\u30a4\u30f3\u69cb\u7bc9\r\n        GridPane grid = new GridPane();\r\n        int rowIndex = 0;\r\n        int colIndex = 0;\r\n        grid.add(recordingButton, colIndex++, rowIndex, 1, 2);\r\n        grid.add(stopButton, colIndex++, rowIndex, 1, 2);\r\n        grid.add(playbackButton, colIndex++, rowIndex, 1, 2);\r\n        grid.add(saveButton, colIndex++, rowIndex, 1, 2);\r\n        grid.add(loadButton, colIndex++, rowIndex, 1, 2);\r\n        int totalColumns = colIndex;\r\n        rowIndex++;\r\n        rowIndex++;\r\n        colIndex = 0;\r\n        grid.add(region, colIndex, rowIndex++);\r\n        rowIndex++;\r\n        grid.add(openCloseButton, colIndex, rowIndex, totalColumns, 1);\r\n        GridPane.setHalignment(openCloseButton, HPos.RIGHT);\r\n        grid.setId(\"grid\");\r\n\r\n        \/\/ \u30b9\u30bf\u30a4\u30eb\u30b7\u30fc\u30c8\u9069\u7528\r\n        grid.getStylesheets().add(\"jp\/yucchi\/toypiano\/ControlScene.css\");\r\n\r\n        \/\/ \u30c8\u30b0\u30eb\u30b9\u30a4\u30c3\u30c1\u304c\u30aa\u30f3\u306e\u5834\u5408\u30c8\u30b0\u30eb\u30b9\u30a4\u30c3\u30c1\u306e raw \u4ee5\u5916\u96a0\u3057\u3001\u30c6\u30ad\u30b9\u30c8\u5909\u66f4\r\n        openCloseButton.setOnAction(ae -> {\r\n            if (openCloseButton.isSelected()) {\r\n                grid.setLayoutY(-grid.sceneToLocal(openCloseButton.localToScene(0, 0)).getY());\r\n                openCloseButton.setText(\"Open\");\r\n            } else {\r\n                grid.setLayoutY(0.0d);\r\n                openCloseButton.setText(\"Close\");\r\n            }\r\n        });\r\n        return grid;\r\n    }\r\n\r\n    private void openAnimation() {\r\n        Timeline openAnimation = new Timeline(\r\n                new KeyFrame(\r\n                        new Duration(0.0d),\r\n                        new KeyValue(angleX, 0.0d, Interpolator.EASE_BOTH),\r\n                        new KeyValue(angleY, 0.0d, Interpolator.EASE_BOTH)\r\n                ),\r\n                new KeyFrame(\r\n                        new Duration(1_000.0d),\r\n                        new KeyValue(angleX, 45, Interpolator.EASE_BOTH),\r\n                        new KeyValue(angleY, 360, Interpolator.EASE_BOTH)\r\n                ));\r\n        openAnimation.setCycleCount(1);\r\n        openAnimation.play();\r\n    }\r\n\r\n    private void playBackAnimation() {\r\n        Timeline playBackAnimation = new Timeline(\r\n                new KeyFrame(\r\n                        new Duration(0.0d),\r\n                        new KeyValue(angleX, 0.0d, Interpolator.EASE_BOTH),\r\n                        new KeyValue(angleY, 0.0d, Interpolator.EASE_BOTH),\r\n                        new KeyValue(angleZ, 0.0d, Interpolator.EASE_BOTH)\r\n                ),\r\n                new KeyFrame(\r\n                        new Duration(1_000.0d),\r\n                        new KeyValue(angleX, 0.0d, Interpolator.EASE_BOTH),\r\n                        new KeyValue(angleY, 360.0d, Interpolator.EASE_BOTH),\r\n                        new KeyValue(angleZ, 0.0d, Interpolator.EASE_BOTH)\r\n                ));\r\n        playBackAnimation.setCycleCount(1);\r\n        playBackAnimation.play();\r\n\r\n    }\r\n\r\n    private void recording() {\r\n        recordingAnimation = new AnimationTimer() {\r\n            long recordingStartTime;\r\n            private boolean rec;\r\n\r\n            @Override\r\n            public void handle(long now) {\r\n                if (!rec) {\r\n                    recordingStartTime = now;\r\n                    rec = true;\r\n                }\r\n                \/\/ \u6642\u9593(actionEventTime)\u306e\u521d\u671f\u5316\r\n                actionEventTime = now - recordingStartTime;\r\n            }\r\n        };\r\n        recordingAnimation.start();\r\n    }\r\n\r\n    private void recordingStop() {\r\n        if (recording) {\r\n            recordingLastTime = actionEventTime;\r\n            \/\/ \u30ec\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u4e2d\u3067\u3042\u308c\u3070\u30ec\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u30b9\u30c8\u30c3\u30d7\u3092\u8a18\u9332\r\n            eventRecording.add(new EventRecording(recordingLastTime, \"FINISH\", \"FINISH\"));\r\n            recordingAnimation.stop();\r\n            recordingAnimation = null;\r\n            recording = false;\r\n        } else {\r\n            playbackAnimation.stop();\r\n        }\r\n        resetKeyboard();\r\n    }\r\n\r\n    private void playback() {\r\n        playbackAnimation = new AnimationTimer() {\r\n            int i = 0;\r\n            boolean playback;\r\n            long playbackStartTime;\r\n            private long playbackTime;\r\n            \/\/ \u30ab\u30e1\u30e9\u7528\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\r\n            \/\/ \u65b9\u4f4d\u89d2\r\n            private double azimuth;\r\n            \/\/ \u524d\u56de\u6642\u9593\r\n            private long previousHandledTime;\r\n            \/\/ \u56de\u8ee2\u901f\u5ea6\r\n            private final DoubleProperty angularVelocityProperty = new SimpleDoubleProperty(5.0d);\r\n            \/\/ \u30ab\u30e1\u30e9\u9ad8\u3055\r\n            private final DoubleProperty heightProperty = new SimpleDoubleProperty(-250.0d);\r\n            \/\/ \u534a\u5f84\r\n            private final double radius = 750.0d;\r\n            \/\/ \u898b\u4e0b\u308d\u3057\u89d2\u5ea6\r\n            private final double downAngle = Math.toDegrees(Math.atan(-1.0d * heightProperty.getValue() \/ radius));\r\n\r\n            @Override\r\n            public void handle(long now) {\r\n                if (!playback) {\r\n                    playbackStartTime = now;\r\n                    playback = true;\r\n                }\r\n\r\n                \/\/ \u6642\u9593(playbackTime)\u306e\u521d\u671f\u5316\r\n                playbackTime = now - playbackStartTime;\r\n                \/\/ eventRecording \u306e\u30c7\u30fc\u30bf\u306b\u57fa\u3065\u304d\u30d7\u30ec\u30a4\u30d0\u30c3\u30af\u3055\u305b\u308b\r\n                if (eventRecording.size() > i && eventRecording.get(i).getEventTime() <= playbackTime) {\r\n                    doEvent(eventRecording.get(i).getEventProducer(), eventRecording.get(i).getEventType());\r\n                    i++;\r\n                }\r\n                \/\/ \u30b5\u30d6\u30ab\u30e1\u30e9\u3092\u534a\u5f84 SUBCAMERA_RADIUS \u306e\u5186\u306e\u4e2d\u5fc3\u3080\u3051\u3001\u4e2d\u5fc3\u306b\u898b\u4e0b\u308d\u3059\u3088\u3046\u306b\u64ae\u5f71\u3059\u308b\r\n                \/\/ \u56de\u8ee2\u30b9\u30d4\u30fc\u30c9\u3082\u524d\u5074\u3068\u5f8c\u308d\u5074\u3067\u5909\u3048\u308b\r\n                if ((0.0d <= azimuth &#038;&#038; azimuth < 90.0d || 270.0d < azimuth)\r\n                        &#038;&#038; (0.0d < (azimuth % 360.0d) &#038;&#038; (azimuth % 360.0d) < 90.0d) || 270.0d < (azimuth % 360.0d)) {\r\n                    azimuth += angularVelocityProperty.get() * (playbackTime - previousHandledTime) \/ 1_000_000_000.0d;\r\n                    previousHandledTime = playbackTime;\r\n                } else {\r\n                    azimuth += angularVelocityProperty.get() * 35.0d * (playbackTime - previousHandledTime) \/ 1_000_000_000.0d;\r\n                    previousHandledTime = playbackTime;\r\n                }\r\n                \/\/ \u30ab\u30e1\u30e9\u79fb\u52d5\u53ca\u3073\u56de\u8ee2\r\n                xPos.set(Math.sin(Math.toRadians(azimuth)) * radius);\r\n                zPos.set(-1.0d * Math.cos(Math.toRadians(azimuth)) * radius);\r\n                yPos.set(heightProperty.getValue());\r\n                subCam.getTransforms().setAll(new Rotate(-1.0d * azimuth, Rotate.Y_AXIS), new Rotate(-1.0d * downAngle, Rotate.X_AXIS));\r\n                \/\/ \u30d7\u30ec\u30a4\u30d0\u30c3\u30af\u7d42\u4e86\u51e6\u7406\r\n                if (eventRecording.get(eventRecording.size() - 1).getEventTime() < playbackTime) {\r\n                    stopButton.setDisable(true);\r\n                    recordingButton.setDisable(false);\r\n                    playbackButton.setDisable(false);\r\n                    saveButton.setDisable(false);\r\n                    loadButton.setDisable(false);\r\n                    activePlayback = false;\r\n                    recordingStop();\r\n                }\r\n            }\r\n\r\n            private void doEvent(String eventProducer, String eventType) {\r\n                if (eventProducer != null &#038;&#038; eventType != null) {\r\n                    switch (eventProducer) {\r\n                        case \"F\":\r\n                            if (eventType.equals(\"TOUCH_PRESSED\")) {\r\n                                pressedWhiteKeyBoard(f, keyboard_f, whiteKeyBoardDepth);\r\n                            } else {\r\n                                releasedKeyBoard(keyboard_f);\r\n                            }\r\n                            break;\r\n\r\n                        case \"G\":\r\n                            if (eventType.equals(\"TOUCH_PRESSED\")) {\r\n                                pressedWhiteKeyBoard(g, keyboard_g, whiteKeyBoardDepth);\r\n                            } else {\r\n                                releasedKeyBoard(keyboard_g);\r\n                            }\r\n                            break;\r\n\r\n                        case \"A\":\r\n                            if (eventType.equals(\"TOUCH_PRESSED\")) {\r\n                                pressedWhiteKeyBoard(a, keyboard_a, whiteKeyBoardDepth);\r\n                            } else {\r\n                                releasedKeyBoard(keyboard_a);\r\n                            }\r\n                            break;\r\n\r\n                        case \"B\":\r\n                            if (eventType.equals(\"TOUCH_PRESSED\")) {\r\n                                pressedWhiteKeyBoard(b, keyboard_b, whiteKeyBoardDepth);\r\n                            } else {\r\n                                releasedKeyBoard(keyboard_b);\r\n                            }\r\n                            break;\r\n\r\n                        case \"F_S\":\r\n                            if (eventType.equals(\"TOUCH_PRESSED\")) {\r\n                                pressedBlackKeyBoard(f_s, keyboard_f_s, blackKeyBoardDepth);\r\n                            } else {\r\n                                releasedKeyBoard(keyboard_f_s);\r\n                            }\r\n                            break;\r\n\r\n                        case \"G_S\":\r\n                            if (eventType.equals(\"TOUCH_PRESSED\")) {\r\n                                pressedBlackKeyBoard(g_s, keyboard_g_s, blackKeyBoardDepth);\r\n                            } else {\r\n                                releasedKeyBoard(keyboard_g_s);\r\n                            }\r\n                            break;\r\n\r\n                        case \"A_S\":\r\n                            if (eventType.equals(\"TOUCH_PRESSED\")) {\r\n                                pressedBlackKeyBoard(a_s, keyboard_a_s, blackKeyBoardDepth);\r\n                            } else {\r\n                                releasedKeyBoard(keyboard_a_s);\r\n                            }\r\n                            break;\r\n\r\n                        case \"FINISH\":\r\n                            break;\r\n\r\n                        default:\r\n                            dameyo.play();\r\n                            System.out.println(\"(>_<\uff61)\");\r\n                    }\r\n                }\r\n            }\r\n        };\r\n        playbackAnimation.start();\r\n    }\r\n\r\n    private void changeCursorStyle(Node node) {\r\n\r\n        node.setOnMouseEntered(mouseEvent -> {\r\n            node.cursorProperty().setValue(Cursor.OPEN_HAND);\r\n        });\r\n\r\n        node.setOnMousePressed(mouseEvent -> {\r\n            node.cursorProperty().setValue(Cursor.CLOSED_HAND);\r\n        });\r\n\r\n        node.setOnMouseExited(mouseEvent -> {\r\n            node.cursorProperty().setValue(Cursor.DEFAULT);\r\n        });\r\n\r\n    }\r\n\r\n    private void resetKeyboard() {\r\n\r\n        releasedKeyBoard(keyboard_f);\r\n        releasedKeyBoard(keyboard_g);\r\n        releasedKeyBoard(keyboard_a);\r\n        releasedKeyBoard(keyboard_b);\r\n        releasedKeyBoard(keyboard_f_s);\r\n        releasedKeyBoard(keyboard_g_s);\r\n        releasedKeyBoard(keyboard_a_s);\r\n\r\n    }\r\n\r\n    private void subCamReset() {\r\n\r\n        subCam.getTransforms().setAll(new Rotate(0.0d, 0.0d, 0.0d));\r\n\r\n        xPos.set(0.0d);\r\n        yPos.set(0.0d);\r\n        zPos.set(-600.0d);\r\n\r\n    }\r\n\r\n    @Override\r\n    public void pressedWhiteKeyBoard(AudioClip ac, Box keyBoard, double keyBoardDepth) {\r\n        ac.play();\r\n        keyBoard.getTransforms().setAll(new Rotate(WHITE_KEYBOARD_DOWN_ANGLE, 0.0d, 0.0d, keyBoardDepth \/ 2, Rotate.X_AXIS));\r\n    }\r\n\r\n    @Override\r\n    public void pressedBlackKeyBoard(AudioClip ac, Box keyBoard, double keyBoardDepth) {\r\n        ac.play();\r\n        keyBoard.getTransforms().setAll(new Rotate(BLACK_KEYBOARD_DOWN_ANGLE, 0.0d, 0.0d, keyBoardDepth \/ 2, Rotate.X_AXIS));\r\n    }\r\n\r\n    @Override\r\n    public void releasedKeyBoard(Box keyBoard) {\r\n        keyBoard.getTransforms().setAll(new Rotate(0.0d, 0.0d, 0.0d));\r\n    }\r\n\r\n    @Override\r\n    public void recordingEvent(boolean recording, List<EventRecording> eventRecording, long actionEventTime, Box keyboard, TouchEvent te) {\r\n        if (recording) {\r\n            eventRecording.add(new EventRecording(actionEventTime, keyboard.getUserData().toString(), te.getEventType().toString()));\r\n        }\r\n    }\r\n}\r\n\r\n\r\n\r\n<\/pre>\n<\/p>\n<p><pre title=\"ControlScene.css\">\r\n\r\n\/* \r\n    Created on : 2014\/12\/10, 23:58:18\r\n    Author     : Yucchi\r\n*\/\r\n\r\n#grid {\r\n    -fx-hgap: 5px;\r\n    -fx-vgap: 1px;\r\n    -fx-alignment: center;\r\n    -fx-background-color: TRANSPARENT;\r\n    -fx-padding: 7px 7px 7px 7px;\r\n    -fx-opacity: 0.9;\r\n}\r\n\r\n#spacer {\r\n    -fx-min-height: 1px;\r\n}\r\n\r\n#open-close-toggle-button {\r\n    -fx-background-color: TRANSPARENT;\r\n    -fx-text-fill: hotpink;\r\n    -fx-font-size: 10pt;\r\n    -fx-font-weight: bold;\r\n}\r\n\r\n#open-close-toggle-button:hover {\r\n    -fx-background-color: TRANSPARENT;\r\n    -fx-text-fill: red;\r\n}\r\n\r\n#open-close-toggle-button:pressed{\r\n    -fx-background-color: TRANSPARENT;\r\n    -fx-text-fill: lightgreen;\r\n}\r\n\r\n\/* Button *\/\r\n.button {\r\n    -fx-background-color: hotpink;\r\n    -fx-background-radius: 30;\r\n    -fx-background-insets: 0;\r\n    -fx-font-size: 10pt;\r\n    -fx-font-weight: bold;\r\n    -fx-text-fill: White;\r\n}\r\n\r\n.button:hover {\r\n    -fx-background-color: deeppink ;\r\n    -fx-text-fill: yellow ;\r\n    -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 5, 0.0 , 0 , 1 );\r\n}\r\n\r\n.button:pressed {\r\n    -fx-background-color: aliceblue;\r\n    -fx-text-fill: deeppink;\r\n}\r\n\r\n\r\n<\/pre>\n<\/p>\n<p>\u6700\u5f8c\u307e\u3067\u8aad\u3093\u3067\u304f\u3060\u3055\u3063\u3066\u3042\u308a\u304c\u3068\u3046\u3054\u3056\u3044\u307e\u3059\u3002<\/p>\n<p>\u611f\u8b1d\u3092\u3053\u3081\u3066\u6ce8\u610f\u304c\u5fc5\u8981\u306a\u3053\u3068\u3092\u66f8\u3044\u3066\u304a\u304d\u307e\u3059\u3002<\/p>\n<p>\u30bf\u30c3\u30c1\u30a4\u30f3\u30bf\u30d5\u30a7\u30fc\u30b9\u3092\u4f7f\u3063\u3066\u3044\u308b\u306e\u3067\u6b21\u306e\u4f8b\u5916\u304c\u6295\u3052\u3089\u308c\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002<\/p>\n<p><font color=\"#666666\">Exception in thread &#8220;JavaFX Application Thread&#8221; java.lang.RuntimeException: Too many touch points reported<\/font><\/p>\n<p>\u3053\u308c\u304c\u6295\u3052\u3089\u308c\u3066\u3082\u52d5\u3044\u3066\u3044\u308c\u3070\u3044\u3044\u306e\u3067\u3059\u304c\u30bf\u30c3\u30c1\u304c\u52b9\u304b\u306a\u304f\u306a\u308b\u5834\u5408\u304c\u3042\u308a\u307e\u3059\u3002\uff08\u30de\u30a6\u30b9\u306f\u52d5\u304d\u307e\u3059\uff09<\/p>\n<p>Twitter \u3067\u3064\u3076\u3084\u3044\u305f\u3089 @aoetk \u3055\u3093\u304b\u3089\u6b21\u306e\u3088\u3046\u306a\u30a2\u30c9\u30d0\u30a4\u30b9\u3092\u3044\u305f\u3060\u304d\u307e\u3057\u305f\u3002<\/p>\n<p>\u300c\u51e6\u7406\u3092\u975e\u540c\u671f\u306b\u3059\u308b\u306e\u3082\u4e00\u3064\u306e\u624b\u3067\u3059\u306d\u3002\u30bf\u30c3\u30c1\u3060\u3068\u3053\u306e\u8fba\u304c\u3069\u3046\u3057\u3066\u3082\u30b7\u30d3\u30a2\u306b\u306a\u308a\u307e\u3059\u306d\u3048\u3002<\/p>\n<p>Windows Store\u30a2\u30d7\u30ea\u958b\u767a\u306b\u4f7f\u3046WinRT API\u3067\u306f\u300150\u30df\u30ea\u79d2\u4ee5\u4e0a\u639b\u304b\u308b\u51e6\u7406\u306f\u975e\u540c\u671f\u306b\u305b\u3088\u3068\u3044\u308f\u308c\u3066\u3044\u308b\u3088\u3046\u3067\u3059\u3002\u300d<\/p>\n<p>\u3042\u308a\u304c\u3068\u3046\u3054\u3056\u3044\u307e\u3057\u305f\u3002(^_^)<\/p>\n<p>\u65e9\u901f\u30a4\u30d9\u30f3\u30c8\u51e6\u7406\u3092\u4e0b\u8a18\u306e\u3088\u3046\u306b\u975e\u540c\u671f\u306b\u5909\u66f4\u3057\u3066\u307f\u307e\u3057\u305f\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color=\"#666666\">keyboard_f.setOnTouchPressed(te -&gt; {<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Task&lt;Void&gt; task = new Task&lt;Void&gt;() {<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected Void call() throws Exception {<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; recordingEvent(recording, eventRecording, actionEventTime, keyboard_f, te);<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Platform.runLater(() -&gt; {<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pressedWhiteKeyBoard(f, keyboard_f, whiteKeyBoardDepth);<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; executor_1.execute(task);<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br \/><\/font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/p>\n<p>\u6b8b\u5ff5\u306a\u304c\u3089\u6539\u5584\u3055\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002<\/p>\n<p>\u4f55\u304c\u60aa\u3044\u306e\u304b\u89e3\u3089\u305a\u3069\u3046\u3057\u3088\u3046\u3063\u3066\u60a9\u3093\u3067\u3044\u305f\u306e\u3067\u3059\u304c\u4eca\u5e74\u306e\uff19\u6708\u306e\u672b\u306b\u8cfc\u5165\u3057\u305f VAIO \u30ce\u30fc\u30c8\u3067\u52d5\u304b\u3057\u305f\u3089\u5168\u7136\u554f\u984c\u306a\u3057\u3067\u3057\u305f\u3002<\/p>\n<p>\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u7d44\u3093\u3067\u3044\u305f PC \u3060\u3051\u306a\u306e\u3067\u3072\u3087\u3063\u3068\u3057\u305f\u3089\u30cf\u30fc\u30c9\u306e\u554f\u984c\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002<\/p>\n<p>\u30bf\u30c3\u30c1\u30d1\u30cd\u30eb\u306e\u6027\u80fd\uff1f<\/p>\n<p>\u30bf\u30c3\u30c1\u30d1\u30cd\u30eb\u306e\u30c9\u30e9\u30a4\u30d0\u3068\u304b\uff1f<\/p>\n<p>\u4f55\u306f\u3068\u3082\u3042\u308c\u65b0\u3057\u3044\u65b9\u306e PC \u3067\u554f\u984c\u306a\u3044\u304b\u3089\u826f\u3057\u3068\u3057\u307e\u3057\u3087\u3046\u3002(\u30f2\u30d2<\/p>\n<p>\u3082\u3046\u4e00\u3064\u3001\u30bf\u30c3\u30c1\u30a4\u30f3\u30bf\u30d5\u30a7\u30fc\u30b9\u3092\u4f7f\u3063\u3066\u3044\u308b\u306e\u3067\u30d4\u30a2\u30ce\u3092\u6f14\u594f\u3057\u3066\u3044\u308b\u3068\u304d\u306b\u30bf\u30c3\u30c1\u30c9\u30e9\u30c3\u30b0\u304c\u767a\u751f\u3057\u3066\u4e0d\u7528\u610f\u306b\u52d5\u3044\u3066\u3057\u307e\u3046\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>\u3053\u308c\u3092\u9632\u6b62\u3059\u308b\u305f\u3081\u306b\u82e6\u8089\u306e\u7b56\u3068\u3057\u3066\u6b21\u306e\u3088\u3046\u306a\u3053\u3068\u3092\u3057\u307e\u3057\u305f\u3002<\/p>\n<p>\u3053\u308c\u304c\u6b63\u3057\u3044\u304b\u3069\u3046\u304b\u306f\u89e3\u308a\u307e\u305b\u3093\u304c\u4f55\u3089\u304b\u306e\u51e6\u7406\u304c\u5fc5\u8981\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp; <font color=\"#666666\">&nbsp;&nbsp;&nbsp; \/\/ \u30d7\u30ec\u30a4\u30d0\u30c3\u30af\u4ee5\u5916\u306e\u30bf\u30c3\u30c1\u30c9\u30e9\u30c3\u30b0\u3092\u7981\u6b62\u3055\u305b\u308b\u305f\u3081\u306b<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; subScene.setOnTouchPressed(te -&gt; {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; touchPressedCount++; \/\/ \u30d5\u30a3\u30fc\u30eb\u30c9\u3078\u30a2\u30af\u30bb\u30b9 \u53d6\u6271\u6ce8\u610f<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; subScene.setOnTouchReleased(te -&gt; {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; touchReleasedCount++; \/\/ \u30d5\u30a3\u30fc\u30eb\u30c9\u3078\u30a2\u30af\u30bb\u30b9 \u53d6\u6271\u6ce8\u610f<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp; \/\/ \u7565<\/font><\/p>\n<p><font color=\"#666666\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; subScene.setOnMouseDragged(event -&gt; {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (touchPressedCount == touchReleasedCount || activePlayback) {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; angleX.set(anchorAngleX &#8211; (anchorY &#8211; event.getSceneY()));<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; angleY.set(anchorAngleY + anchorX &#8211; event.getSceneX());<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<\/font><\/p>\n<p>3D \u540c\u69d8\u30bf\u30c3\u30c1\u30a4\u30f3\u30bf\u30d5\u30a7\u30fc\u30b9\u3092\u4f7f\u3063\u305f\u89e3\u8aac\u304c\u5c11\u306a\u3044\u306e\u3067\u3053\u3046\u3044\u3063\u305f\u3068\u304d\u306e\u5b9a\u756a\u51e6\u7406\u3068\u3044\u3046\u306e\u304c\u826f\u304f\u89e3\u308a\u307e\u305b\u3093\u3002<\/p>\n<p>\u5148\u65e5\u3082\u30de\u30a6\u30b9\u30b9\u30af\u30ed\u30fc\u30eb\u306b\u3088\u308b\u30ab\u30e1\u30e9\u30dd\u30b8\u30b7\u30e7\u30f3\u306e\u5909\u66f4\u3067\u968f\u5206\u60a9\u307f\u307e\u3057\u305f\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/?p=1750\" target=\"_blank\">JavaFX\u3067\u30de\u30a6\u30b9\u30db\u30a4\u30fc\u30eb\u3092\u4f7f\u3063\u3066\u306e\u30ba\u30fc\u30e0\u30a4\u30f3\u30ba\u30fc\u30e0\u30a2\u30a6\u30c8\u306f\u53ef\u80fd\u304b\uff1f<\/a><\/p>\n<p>\u30bf\u30c3\u30c1\u30a4\u30f3\u30bf\u30d5\u30a7\u30fc\u30b9\u306e\u5b8c\u5168\u7121\u6b20\u306e\u4f7f\u3044\u65b9\u3092\u77e5\u308a\u305f\u3044\u4eca\u65e5\u3053\u306e\u9803\u3067\u3059\u3002<\/p>\n<p>\u3042\u3068\u3001\u30ab\u30e1\u30e9\u306e\u79fb\u52d5\u3001\u56de\u8ee2\u306a\u3093\u3067\u3059\u304c\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3067\u306f\u3001\u898b\u4e0b\u308d\u3057\u89d2\u5ea6(X \u8ef8)\u3068\u4e2d\u5fc3\u3078\u306e\u89d2\u5ea6(Y \u8ef8)\u3067\u30ab\u30e1\u30e9\u3092\u56de\u8ee2\u3055\u305b\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color=\"#666666\">\/\/ \u30ab\u30e1\u30e9\u79fb\u52d5\u53ca\u3073\u56de\u8ee2<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xPos.set(Math.sin(Math.toRadians(azimuth)) * radius);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; zPos.set(-1.0d * Math.cos(Math.toRadians(azimuth)) * radius);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yPos.set(heightProperty.getValue());<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; subCam.getTransforms().setAll(new Rotate(-1.0d * azimuth, Rotate.Y_AXIS), new Rotate(-1.0d * downAngle, Rotate.X_AXIS));<\/font><\/p>\n<p>\u3053\u306e\u30b3\u30fc\u30c9\u306e\u6700\u5f8c\u306e\u884c\u3067\u30ab\u30e1\u30e9\u3092\u56de\u8ee2\u3055\u305b\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>\u3053\u3053\u3067\u6700\u5f8c\u306e\u884c\u3092\u6b21\u306e\u3088\u3046\u306a\u30b3\u30fc\u30c9\u3092\u66f8\u304f\u3068\u306f\u307e\u308a\u307e\u3059\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color=\"#666666\">&nbsp; ryPos.set(-1.0d * azimuth);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rxPos.set(-1.0d * downAngle);<\/font><\/p>\n<p>\u7406\u5c48\u7684\u306b\u306f\u540c\u3058\u3088\u3046\u306b\u611f\u3058\u308b\u306e\u3067\u3059\u304c\u307e\u3063\u305f\u304f\u9055\u3044\u307e\u3059\u3002<\/p>\n<p>\u6b8b\u5ff5\u306a\u304c\u3089\u3068\u3093\u3067\u3082\u306a\u3044\u30ab\u30e1\u30e9\u30ef\u30fc\u30af\u3068\u306a\u3063\u3066\u3057\u307e\u3044\u307e\u3059\u3002<\/p>\n<p>\u898b\u4e0b\u308d\u3057\u89d2\u3092\u3064\u3051\u305a\u306b Y \u8ef8\u3060\u3051\u56de\u8ee2\u3055\u305b\u308b\u306e\u3067\u3042\u308c\u3070\u6b21\u306e\u30b3\u30fc\u30c9\u3067\u554f\u984c\u3042\u308a\u307e\u305b\u3093\u3002<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color=\"#666666\">\/\/ \u30ab\u30e1\u30e9\u79fb\u52d5\u53ca\u3073\u56de\u8ee2<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xPos.set(Math.sin(Math.toRadians(azimuth)) * radius);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; zPos.set(-1.0d * Math.cos(Math.toRadians(azimuth)) * radius);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yPos.set(heightProperty.getValue());<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ryPos.set(-1.0d * azimuth);<\/font><\/p>\n<p>\u56de\u8ee2\u3055\u305b\u308b\u30b3\u30fc\u30c9\u3092\u66f8\u304f\u3068\u304d\u306f\u6ce8\u610f\u304c\u5fc5\u8981\u3067\u3059\u3002<\/p>\n<p>\u3042\u3068\u306f\u3044\u305f\u3063\u3066\u30b7\u30f3\u30d7\u30eb\u306a\u3082\u306e\u306a\u306e\u3067\u4f5c\u3063\u3066\u904a\u3093\u3067\u307f\u308b\u306e\u3082\u3044\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002<\/p>\n<p>\u5b9f\u969b\u306b Box \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3060\u3051\u3092\u4f7f\u3044\u79fb\u52d5\u3068\u56de\u8ee2\u3060\u3051\u3057\u304b\u3055\u305b\u3066\u3044\u307e\u305b\u3093\u3002<\/p>\n<p>OneDrive \u306b\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u7f6e\u3044\u3066\u3042\u308a\u307e\u3059\u306e\u3067\u904a\u3093\u3067\u307f\u305f\u3044\u65b9\u306f\u6b21\u306e\u30ea\u30f3\u30af\u304b\u3089\u3069\u3046\u305e\u3002<\/p>\n<p><a href=\"https:\/\/onedrive.live.com\/redir?resid=EAE4ED7554BC7AB6!34658&amp;authkey=!AP29iHq_NpAEKiM&amp;ithint=folder%2c\">https:\/\/onedrive.live.com\/redir?resid=EAE4ED7554BC7AB6!34658&amp;authkey=!AP29iHq_NpAEKiM&amp;ithint=folder%2c<\/a><\/p>\n<p>\u4e00\u5fdc\u3001\u4f55\u304b\u30c8\u30e9\u30d6\u30eb\u304c\u8d77\u3053\u3063\u3066\u640d\u5bb3\u304c\u767a\u751f\u3057\u3066\u3082\u8cac\u4efb\u306f\u4e00\u5207\u8ca0\u3048\u307e\u305b\u3093\u306e\u3067(^_^;)<\/p>\n<p>\/**<br \/>*<br \/>* @\u304a\u307e\u3051\u306e\u304a\u77e5\u3089\u305b<br \/>*&nbsp; <br \/>* <a href=\"http:\/\/yucchi.jp\/blog\/?p=1772\" target=\"_blank\">SwingNode\u3068TextFlow<\/a><br \/>*<br \/>* <a href=\"http:\/\/yucchi.jp\/blog\/?p=1776\" target=\"_blank\">JavaFX \u3067\u82f1\u8a9e\u529b\u3092\u88dc\u3046<\/a><br \/>*<br \/>*\/<\/p>\n<p>\u6700\u5f8c\u306b\u3072\u3068\u8a00<\/p>\n<p>JavaFX \u697d\u3057\u3044\uff01<\/p>\n<div class='wp_social_bookmarking_light'>\n            <div class=\"wsbl_hatena\"><a href='\/\/b.hatena.ne.jp\/add?mode=confirm&url=http%3A%2F%2Fyucchi.jp%2Fblog%2F%3Fp%3D1832&title=JavaFX%20%E3%81%AE%E6%A8%99%E6%BA%96%E6%A9%9F%E8%83%BD%E3%81%A0%E3%81%91%E3%81%A7%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%81%AA%203D%20%E3%83%88%E3%82%A4%E3%83%94%E3%82%A2%E3%83%8E%E3%82%92%E3%81%A4%E3%81%8F%E3%82%8D%E3%81%86' title='\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u3092\u306f\u3066\u306a\u30d6\u30c3\u30af\u30de\u30fc\u30af\u306b\u8ffd\u52a0' rel=nofollow class='wp_social_bookmarking_light_a' target=_blank><img src='http:\/\/yucchi.jp\/blog\/wp-content\/plugins\/wp-social-bookmarking-light\/public\/images\/hatena.gif' alt='\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u3092\u306f\u3066\u306a\u30d6\u30c3\u30af\u30de\u30fc\u30af\u306b\u8ffd\u52a0' title='\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u3092\u306f\u3066\u306a\u30d6\u30c3\u30af\u30de\u30fc\u30af\u306b\u8ffd\u52a0' width='16' height='12' class='wp_social_bookmarking_light_img' \/><\/a><\/div>\n            <div class=\"wsbl_facebook\"><a href='http:\/\/www.facebook.com\/share.php?u=http%3A%2F%2Fyucchi.jp%2Fblog%2F%3Fp%3D1832&t=JavaFX%20%E3%81%AE%E6%A8%99%E6%BA%96%E6%A9%9F%E8%83%BD%E3%81%A0%E3%81%91%E3%81%A7%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%81%AA%203D%20%E3%83%88%E3%82%A4%E3%83%94%E3%82%A2%E3%83%8E%E3%82%92%E3%81%A4%E3%81%8F%E3%82%8D%E3%81%86' title='Facebook \u306b\u30b7\u30a7\u30a2' rel=nofollow class='wp_social_bookmarking_light_a' target=_blank><img src='http:\/\/yucchi.jp\/blog\/wp-content\/plugins\/wp-social-bookmarking-light\/public\/images\/facebook.png' alt='Facebook \u306b\u30b7\u30a7\u30a2' title='Facebook \u306b\u30b7\u30a7\u30a2' width='16' height='16' class='wp_social_bookmarking_light_img' \/><\/a><\/div>\n            <div class=\"wsbl_google_plus_one\"><g:plusone size=\"medium\" annotation=\"none\" href=\"http:\/\/yucchi.jp\/blog\/?p=1832\" ><\/g:plusone><\/div>\n            <div class=\"wsbl_twitter\"><a href=\"https:\/\/twitter.com\/share\" class=\"twitter-share-button\" data-url=\"http:\/\/yucchi.jp\/blog\/?p=1832\" data-text=\"JavaFX \u306e\u6a19\u6e96\u6a5f\u80fd\u3060\u3051\u3067\u30b7\u30f3\u30d7\u30eb\u306a 3D \u30c8\u30a4\u30d4\u30a2\u30ce\u3092\u3064\u304f\u308d\u3046\" data-lang=\"ja\">Tweet<\/a><\/div>\n    <\/div>\n<br class='wp_social_bookmarking_light_clear' \/>\n","protected":false},"excerpt":{"rendered":"<p>\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u306f\u3001JavaFX Advent Calendar 2014, 11\u65e5\u76ee\u3067\u3059\u3002 \u6628\u65e5\u306f @toruwest \u3055\u3093\u306e\u300cJavaFX\u306eTreeView\u3067\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u3057\u3066\u307f\u308b\u300d\u3067\u3057\u305f\u3002 \u660e\u65e5\u306f @skrb \u3055\u3093\u306e\u300cJava Advent Calendar\u3068\u4e00\u7dd2\u306b\u306a\u306b\u304b\u66f8\u304d\u307e\u3059\u300d\u3067\u3059\u3002 \u4eca\u5e74\u3082\u6b8b\u308a\u5c11\u306a\u304f\u306a\u3063\u3066\u304d\u3066\u3044\u308d\u3044\u308d\u3068\u5fd9\u3057\u304f\u306a\u3063\u3066\u304d\u307e\u3057\u305f\u3002 \u305d\u3093\u306a\u4eca\u65e5\u3053\u306e\u9803\u3001\u4f55\u6545\u304b\u300c\u732b\u3075\u3093\u3058\u3083\u305f\u300d\u306e\u30e1\u30ed\u30c7\u30a3\u304c\u30de\u30a4\u30d6\u30fc\u30e0\u3068\u306a\u3063\u3066\u304d\u307e\u3057\u305f\u3002 \u5fd9\u3057\u3044\u306e\u306a\u3089\u732b\u306e\u624b\u3082\u501f\u308a\u305f\u3044\u72b6\u6cc1\u306a\u306e\u306b\u8e0f\u3093\u3058\u3083\u3063\u305f\u3089\u3044\u3051\u306a\u3044\u306e\u306b\u306d\uff01 \u3068\u8a00\u3046\u308f\u3051\u3067\u300c\u732b\u3075\u3093\u3058\u3083\u3063\u305f\u300d\u3092\u5f3e\u304d\u305f\u304f\u306a\u3063\u3066 JavaFX \u3067 ToyPiano \u30a2\u30d7\u30ea\u30b1\u30fc\u2026<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[21],"class_list":["post-1832","post","type-post","status-publish","format-standard","hentry","category-javafx","tag-javafx"],"_links":{"self":[{"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1832","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1832"}],"version-history":[{"count":3,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1832\/revisions"}],"predecessor-version":[{"id":1835,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1832\/revisions\/1835"}],"wp:attachment":[{"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1832"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1832"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1832"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}