﻿{"id":1375,"date":"2013-11-23T17:11:31","date_gmt":"2013-11-23T08:11:31","guid":{"rendered":"http:\/\/yucchi.jp\/blog\/?p=1375"},"modified":"2013-11-28T13:21:19","modified_gmt":"2013-11-28T04:21:19","slug":"duke-%e3%82%92%e6%ad%a9%e3%81%8b%e3%81%9b%e3%81%a6%e3%81%bf%e3%81%9f%e3%80%82-javafx-3d-%e3%82%a2%e3%83%8b%e3%83%a1%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3","status":"publish","type":"post","link":"http:\/\/yucchi.jp\/blog\/?p=1375","title":{"rendered":"Duke \u3092\u6b69\u304b\u305b\u3066\u307f\u305f\u3002 JavaFX 3D \u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3"},"content":{"rendered":"<p>\u4eca\u5e74\u306e JavaOne \u3067\u30c1\u30a7\u30b9\u306e\u99d2\u306b\u626e\u3057\u305f Duke \u304c\u683c\u597d\u826f\u304f\u6b69\u3044\u3066\u3044\u305f\u3002<\/p>\n<p>JavaFX 3D \u30c6\u30af\u30ce\u30ed\u30b8\u30fc\u3092\u99c6\u4f7f\u3057\u305f\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u304c\u62ab\u9732\u3055\u308c\u3066\u4f1a\u5834\u3092\u308f\u304b\u305b\u3066\u3044\u305f\u3002<\/p>\n<p><iframe loading=\"lazy\" height=\"480\" src=\"\/\/www.youtube.com\/embed\/EewNJI3IiII?rel=0\" frameborder=\"0\" width=\"640\" allowfullscreen><\/iframe> <\/p>\n<p>\u3068\u3066\u3082\u7d20\u6575\u3060\u3063\u305f\u304c Maya \u3068\u8a00\u3046\u9ad8\u4fa1\u306a 3DCG \u30bd\u30d5\u30c8\u3068 3DViewer \uff08\u4f55\u6545\u304b\u4eca\u306f\u52d5\u304b\u306a\u3044\u3089\u3057\u3044\uff09\u3092\u4f7f\u3063\u3066\u4f5c\u3089\u308c\u3066\u3044\u308b\u3089\u3057\u3044\u3002\uff08\u672a\u78ba\u8a8d\u3067\u3059\u3002\uff09<\/p>\n<p>\u30cd\u30c3\u30c8\u4e0a\u306b\u3082 3D \u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u4f5c\u6210\u306e\u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb\u3084\u30b5\u30f3\u30d7\u30eb\u3082\u307e\u3060\u898b\u5f53\u305f\u3089\u306a\u3044\u3002<\/p>\n<p>\u3068\u306f\u8a00\u3048\u3001JavaFX 8 \u306b\u306f\u6a19\u6e96\u3067 3DAPI \u304c\u5b9f\u88c5\u3055\u308c\u3066\u3044\u308b\u306e\u3067\u8fd1\u3044\u5c06\u6765\u76ee\u306b\u3059\u308b\u3053\u3068\u3082\u3042\u308b\u3060\u308d\u3046\u3002<\/p>\n<p>\u3067\u3082\u3001\u65b0\u3057\u3044\u7269\u597d\u304d\u306e\u79c1\u306f\u5f85\u3061\u304d\u308c\u306a\u3044\u306e\u3067\u624b\u63a2\u308a\u3067\u30b0\u30ea\u30b0\u30ea\u3057\u3066\u307f\u305f\u3002<\/p>\n<p>\u65e5\u672c\u8a9e\u3067\u306e\u60c5\u5831\u306f\u4e0b\u8a18\u30b5\u30a4\u30c8\u304c\u89e3\u308a\u3084\u3059\u304f\u3066\u826f\u3044\u3067\u3059\u306d\u3002<\/p>\n<p><a href=\"http:\/\/www.torutk.com\/projects\/swe\/wiki\/JavaFX_3D%E3%82%92%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B\" target=\"_blank\">JavaFX 3D\u3092\u7406\u89e3\u3059\u308b<\/a><\/p>\n<p>\u30ab\u30e1\u30e9\u306e\u5186\u8ecc\u9053\u306e\u3055\u305b\u65b9\u306f\u975e\u5e38\u306b\u53c2\u8003\u306b\u306a\u308a\u307e\u3057\u305f\u3002\uff08\uff3e\uff3e\uff09<\/p>\n<p>\/\/ \u611f\u8b1d\u306e\u30b3\u30fc\u30c9<br \/>IntStream.rangeClosed(1, 1_000_000).forEach(i -&gt; {<br \/>&nbsp;&nbsp;&nbsp; System.out.println(&#8220;Thanks!&#8221;);<br \/>});<\/p>\n<p>\u73fe\u5728\u30cd\u30c3\u30c8\u4e0a\u306b\u3042\u308b\u60c5\u5831\u3092\u3042\u3061\u3053\u3068\u304b\u3089\u304b\u304d\u96c6\u3081\u3001\u3061\u3083\u3093\u3068\u8aad\u3081\u306a\u3044\u82f1\u8a9e\u306e API \u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u3092\u683c\u95d8\u3057\u306a\u304c\u3089 Duke \u3092\u6b69\u304b\u305b\u308b\u3053\u3068\u306b\u6210\u529f\u3057\u305f\uff01<\/p>\n<p><video width=\"864\" height=\"486\" controls><source src=\"http:\/\/yucchi.jp\/movie\/Duke_Walk\/DukeWalk_Mini.mp4\" type=\"video\/mp4\">\u3042\u306a\u305f\u304c\u3054\u5229\u7528\u306e\u30d6\u30e9\u30a6\u30b6\u3067\u306f\u518d\u751f\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002<\/video><\/p>\n<p>\u30b5\u30d6\u30b7\u30fc\u30f3\u7528\u306e\u30ab\u30e1\u30e9\u306e\u8a2d\u5b9a\u3092<\/p>\n<p>PerspectiveCamera subCam = new PerspectiveCamera(true);<\/p>\n<p>\u3068\u3059\u308b\u3053\u3068\u306b\u3088\u3063\u3066\u3001\u78ba\u5b9f\u306b\u5ea7\u6a19\u4f4d\u7f6e\u3092\u628a\u63e1\u3059\u308b\u3053\u3068\u306b\u6210\u529f\u3057\u305f\u3002\uff08\u305f\u3076\u3093\u30fb\u30fb\u30fb\uff09<\/p>\n<p>JavaOne \u3068\u540c\u3058\u3053\u3068\u306f\u3067\u304d\u306a\u3044\u304c\u30dc\u30fc\u30c9\u306e\u4e0a\u3092 Duke \u304c\u843d\u3061\u306a\u3044\u3088\u3046\u306b\u884c\u3063\u305f\u308a\u6765\u305f\u308a\u6b69\u304b\u305b\u308b\u3053\u3068\u306b\u3057\u305f\u3002<\/p>\n<p>\u4eca\u56de\u306f\u524d\u56de\u4f7f\u3063\u3066\u3044\u305f\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u30ab\u30e1\u30e9\u306e\u8a2d\u5b9a\u5909\u66f4\u306b\u3088\u3063\u3066\u5c11\u3057\u5909\u66f4\u3057\u3001<\/p>\n<p>\u30e2\u30c7\u30eb\u3082\u81ea\u524d\u3067\u7528\u610f\u3057\u305f\u3002<\/p>\n<p>\u30e1\u30bf\u30bb\u30b3\u30a4\u30a2\u3068\u3044\u3046\u30ea\u30fc\u30ba\u30ca\u30d6\u30eb\u306a 3DCG \u30bd\u30d5\u30c8\u3092\u4f7f\u7528\u3057\u3066\u4f5c\u308a\u307e\u3057\u305f\u3002<\/p>\n<p>\u305f\u3060\u3001\u5f8c\u3067\u89e3\u3063\u305f\u3053\u3068\u3060\u3051\u3069\u4eca\u306f Blender \u3068\u3044\u3046 3DCG \u30bd\u30d5\u30c8\u304c\u4eba\u6c17\u3089\u3057\u3044\u3002<\/p>\n<p>Blender \u306f\u6bd4\u8f03\u7684\u65b0\u3057\u3044\u53c2\u8003\u66f8\u3082\u51fa\u3066\u3044\u308b\u3057\u3001\u96d1\u8a8c\u3084\u30e0\u30c3\u30af\u3067\u3082\u53d6\u308a\u4e0a\u3052\u3089\u308c\u3066\u308b\u6a5f\u4f1a\u304c\u591a\u3044\u3002<\/p>\n<p>\u30e1\u30bf\u30bb\u30b3\u30a4\u30a2\u306f\u4eba\u6c17\u306f\u3042\u308b\u3051\u3069\u65b0\u3057\u3044\u53c2\u8003\u66f8\u3084\u96d1\u8a8c\u306f\u898b\u306a\u3044\u3067\u3059\u306d\u3002<\/p>\n<p>\u3069\u3061\u3089\u306b\u3057\u308d\u4e0d\u5668\u7528\u306a\u79c1\u306b\u306f\u4f7f\u3044\u3053\u306a\u305b\u307e\u305b\u3093\u3002(&gt;_&lt;\uff61)<\/p>\n<p>\u8a71\u3092\u6838\u5fc3\u306b\u623b\u3057\u3066\u30013D \u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u30a2\u30d7\u30ea\u3092\u4f5c\u308b\u306e\u306b\u5fc5\u8981\u306a\u3082\u306e\u3092\u8003\u3048\u3066\u307f\u307e\u3057\u305f\u3002<\/p>\n<p>\u307e\u305a\u3001\u624b\u8db3\u304c\u52d5\u304b\u305b\u308b Duke \u306e\u30e2\u30c7\u30eb\u3002<\/p>\n<p>\u3053\u308c\u306f\u30d1\u30fc\u30c4\u3092\u5206\u3051\u3066\u305d\u308c\u305e\u308c Timeline \u3092\u4f7f\u3063\u3066\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u3055\u305b\u3066\u307f\u307e\u3057\u305f\u3002<\/p>\n<p>\u6b21\u306b\u3001\u30c1\u30a7\u30b9\u30dc\u30fc\u30c9\u3002\u3000\u3068\u3044\u3063\u3066\u3082\u305d\u308c\u3089\u3057\u304d\u3082\u306e\u3067\u3044\u3044\u306e\u3067\u3053\u308c\u3082\u7c21\u5358\u306b\u6e08\u307e\u305b\u307e\u3057\u305f\u3002<\/p>\n<p>\u3042\u3068\u306f\u3053\u308c\u3089\u3092\u30b8\u30e0\u3055\u3093\u304c\u4f5c\u3089\u308c\u305f JFX3DModelImporters \u3092\u4f7f\u308f\u305b\u3066\u3044\u305f\u3060\u304d\u30a4\u30f3\u30dd\u30fc\u30c8\u3057\u307e\u3059\u3002<\/p>\n<p>\u5f8c\u306f\u5ea7\u6a19\u4f4d\u7f6e\u3092\u8abf\u3079\u3066 AnimationTimer \u3092\u4f7f\u3044\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u3055\u305b\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>\u30dc\u30fc\u30c9\u304b\u3089\u843d\u3061\u306a\u3044\u3088\u3046\u306b\u30bf\u30fc\u30f3\u3055\u305b\u3066\u307e\u3059\u3002<\/p>\n<p>\u30bf\u30fc\u30f3\u306e\u90e8\u5206\u3082 Timeline \u3092\u4f7f\u3063\u3066\u307e\u3059\u3002<\/p>\n<p>\u3053\u3093\u306a\u306b AnimationTimer \u3084 Timeline \u3092\u4f7f\u3063\u3066\u554f\u984c\u306a\u3044\u306e\u304b\u306a\u3063\u3066\u601d\u3063\u305f\u308a\u3082\u3057\u307e\u3059\u304c\u52d5\u3044\u3066\u307e\u3059\u3002(\uffe3\u3002\uffe3;)<\/p>\n<p>\u3072\u305f\u3059\u3089\u884c\u3063\u305f\u308a\u6765\u305f\u3057\u3059\u308b\u3060\u3051\u306e\u9762\u767d\u307f\u306e\u7121\u3044\u30a2\u30d7\u30ea\u3068\u306a\u3063\u3066\u307e\u3059\u3002<\/p>\n<p>\u3053\u308c\u3067\u306f\u5bc2\u3057\u3044\u306e\u3067\u97f3\u697d\u3092\u6d41\u3059\u3053\u3068\u306b\u3057\u307e\u3057\u305f\u3002<\/p>\n<p>\u3061\u3087\u3063\u3068\u753b\u9762\u3082\u5bc2\u3057\u3044\u306e\u3067 DUKE WALK \u3068\u6587\u5b57\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30e2\u30c7\u30eb\u3082\u4f5c\u3063\u3066\u8ffd\u52a0\u3057\u307e\u3057\u305f\u3002<\/p>\n<p>\u305b\u3063\u304b\u304f\u3060\u304b\u3089\u3053\u308c\u3082\u52d5\u304b\u3057\u305f\u304f\u306a\u308a\u307e\u3059\u3088\u306d\u3002<\/p>\n<p>\u30aa\u30fc\u30c7\u30a3\u30aa\u30b9\u30da\u30af\u30c8\u30e9\u30e0\u30ea\u30b9\u30ca\u30fc\u3092\u5b9f\u88c5\u3057\u3066\u6587\u5b57\u6570\u306e\u6587\u3060\u3051 0.01 \u79d2\u3054\u3068\u306b\u30b5\u30f3\u30d7\u30ea\u30f3\u30b0\u3057\u3066\u305d\u308c\u3092\u3082\u3068\u306b\u9069\u5f53\u306b\u30b9\u30b1\u30fc\u30ea\u30f3\u30b0\u3055\u305b\u3066\u8cd1\u3084\u304b\u306b\u3057\u307e\u3057\u305f\u3002<\/p>\n<p>\u4ee5\u4e0a\u3001\u975e\u5e38\u306b\u30b7\u30f3\u30d7\u30eb\u306b\u4f5c\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3057\u305f\u3002<\/p>\n<p>\u305f\u3060\u3001\u5f71\u3092\u6620\u3059\u65b9\u6cd5\u304c\u89e3\u3089\u306a\u304b\u3063\u305f\u3002<\/p>\n<p>JavaOne \u306e\u30c7\u30e2\u3082\u5f71\u306f\u7121\u3044\u3088\u3046\u306b\u898b\u3048\u308b\u306e\u3067\u73fe\u6642\u70b9\u3067\u306f\u7121\u7406\u306a\u306e\u304b\u3082\u3057\u308c\u306a\u3044\u3002<\/p>\n<p>\u3053\u308c\u3067\u3082\u79c1\u7684\u306b\u306f Complete Success! (^^)<\/p>\n<p>\u5b8c\u5168\u7248\u306e\u52d5\u753b\u306f\u6b21\u306b\u306a\u308a\u307e\u3059\u3002\u5404\u7a2e\u30ab\u30e1\u30e9\u64cd\u4f5c\u306b\u3088\u308b\u5199\u308a\u65b9\u304c\u7406\u89e3\u3067\u304d\u307e\u3059\u3002<\/p>\n<p><video width=\"864\" height=\"486\" controls><source src=\"http:\/\/yucchi.jp\/movie\/Duke_Walk\/DukeWalk.mp4\" type=\"video\/mp4\">\u3042\u306a\u305f\u304c\u3054\u5229\u7528\u306e\u30d6\u30e9\u30a6\u30b6\u3067\u306f\u518d\u751f\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002<\/video><\/p>\n<p>\u305d\u308c\u3067\u306f\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u8f09\u305b\u3066\u304a\u304d\u307e\u3059\u3002<\/p>\n<p>\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u8a73\u3057\u3044\u5185\u5bb9\u306f\u8aac\u660e\u3057\u307e\u305b\u3093\u304c\u4f55\u3092\u3084\u3063\u3066\u3044\u308b\u304b\u3060\u3044\u305f\u3044\u89e3\u308b\u3088\u3046\u306b\u30b3\u30e1\u30f3\u30c8\u3092\u3044\u308c\u3066\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>\u7279\u306b\u8907\u96d1\u306a\u3053\u3068\u306f\u3057\u3066\u306a\u3044\u306e\u3067\u89e3\u3089\u306a\u3044\u3053\u3068\u306f\u306a\u3044\u3067\u3057\u3087\u3046\u3002<\/p>\n<p>\u6ce8\u610f\u3057\u3066\u6b32\u3057\u3044\u306e\u306f\u3001\u307e\u3060 JavaFX \u89e6\u308a\u521d\u3081\u3066\u9593\u3082\u306a\u3044\u79c1\u304c\u3042\u3061\u3053\u3061\u304b\u3089\u304b\u304d\u96c6\u3081\u305f\u60c5\u5831\u3068\u82f1\u8a9e\u306e API \u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u3068\u306b\u3089\u3081\u3063\u3053\u3057\u3066\u305f\u3076\u3093\u3053\u308c\u3067\u3044\u3044\u306e\u3060\u308d\u3046\u3068\u4f5c\u3063\u305f\u3082\u306e\u3060\u3068\u3044\u3046\u3053\u3068\u3067\u3059\u3002<\/p>\n<p>\u9593\u9055\u3044\u304c\u3042\u308c\u3070\u5fa1\u6559\u793a\u3044\u305f\u3060\u3051\u308c\u3070\u5e78\u3044\u3067\u3059\u3002<\/p>\n<p><pre title=\"DukeWalk.java\">\r\npackage jp.yucchi.dukewalk;\r\n\r\nimport com.interactivemesh.jfx.importer.ImportException;\r\nimport com.interactivemesh.jfx.importer.obj.ObjModelImporter;\r\nimport java.net.URL;\r\nimport java.util.stream.IntStream;\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.beans.binding.When;\r\nimport javafx.beans.property.BooleanProperty;\r\nimport javafx.beans.property.DoubleProperty;\r\nimport javafx.beans.property.SimpleBooleanProperty;\r\nimport javafx.beans.property.SimpleDoubleProperty;\r\nimport javafx.event.ActionEvent;\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.SubScene;\r\nimport javafx.scene.control.Accordion;\r\nimport javafx.scene.control.Button;\r\nimport javafx.scene.control.CheckBox;\r\nimport javafx.scene.control.Label;\r\nimport javafx.scene.control.Slider;\r\nimport javafx.scene.control.TitledPane;\r\nimport javafx.scene.image.Image;\r\nimport javafx.scene.layout.AnchorPane;\r\nimport javafx.scene.layout.Background;\r\nimport javafx.scene.layout.HBox;\r\nimport javafx.scene.media.AudioSpectrumListener;\r\nimport javafx.scene.media.Media;\r\nimport javafx.scene.media.MediaPlayer;\r\nimport javafx.scene.paint.Color;\r\nimport javafx.scene.shape.DrawMode;\r\nimport javafx.scene.shape.MeshView;\r\nimport javafx.scene.transform.Rotate;\r\nimport javafx.stage.Stage;\r\nimport javafx.util.Duration;\r\n\r\npublic class DukeWalk extends Application implements AudioSpectrumListener {\r\n\r\n    \/\/ \u79fb\u52d5\r\n    private final DoubleProperty xPos = new SimpleDoubleProperty(0);\r\n    private final DoubleProperty yPos = new SimpleDoubleProperty(0);\r\n    private final DoubleProperty zPos = new SimpleDoubleProperty(-1_000);\r\n    \/\/ \u30b9\u30b1\u30fc\u30eb\r\n    private final DoubleProperty sxPos = new SimpleDoubleProperty(1.0);\r\n    private final DoubleProperty syPos = new SimpleDoubleProperty(1.0);\r\n    private final DoubleProperty szPos = new SimpleDoubleProperty(1.0);\r\n    \/\/ \u56de\u8ee2\r\n    private final DoubleProperty rxPos = new SimpleDoubleProperty(0);\r\n    private final DoubleProperty ryPos = new SimpleDoubleProperty(0);\r\n    private final DoubleProperty rzPos = new SimpleDoubleProperty(0);\r\n    \/\/ \u8868\u793a\u30e2\u30fc\u30c9\r\n    private final BooleanProperty showWireframe = new SimpleBooleanProperty(false);\r\n    \/\/ \u5ea7\u6a19\r\n    private double anchorAngleX;\r\n    private double anchorAngleY;\r\n    private final DoubleProperty angleX = new SimpleDoubleProperty(0);\r\n    private final DoubleProperty angleY = new SimpleDoubleProperty(0);\r\n    private double anchorX;\r\n    private double anchorY;\r\n    \/\/ Duke \u53cd\u8ee2\u51e6\u7406\u7528\r\n    private final DoubleProperty turnAngleY = new SimpleDoubleProperty(0);\r\n    \/\/ Duke \u624b\u8db3\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u7528\r\n    DoubleProperty angleWalk_r_X = new SimpleDoubleProperty(0);\r\n    DoubleProperty angleWalk_l_X = new SimpleDoubleProperty(0);\r\n    DoubleProperty angleWalk_l_arm = new SimpleDoubleProperty(0);\r\n    DoubleProperty angleWalk_r_arm = new SimpleDoubleProperty(0);\r\n    \/\/ \u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\r\n    private Timeline dukeAnim;\r\n    \/\/ \u30ab\u30e1\u30e9\u7528\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u30bf\u30a4\u30de\u30fc\r\n    private AnimationTimer walkTimer;\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 azimuthRateProperty = new SimpleDoubleProperty(15);\r\n    \/\/ \u30ab\u30e1\u30e9\u9ad8\u3055\r\n    private final DoubleProperty elevationProperty = new SimpleDoubleProperty(7);\r\n    \/\/ \u534a\u5f84\r\n    private static final double SUBCAMERA_RADIUS = 5_500;\r\n    \/\/ Duke \u53cd\u8ee2\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u7528\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\r\n    private Timeline rightTurn;\r\n    private Timeline leftTurn;\r\n    \/\/ BGM\r\n    private final Media bgm = new Media(getClass().getResource(\"music\/bgm.mp3\").toExternalForm());\r\n    \/\/ \u30e1\u30c7\u30a3\u30a2\u30d7\u30ec\u30fc\u30e4\u30fc\r\n    private MediaPlayer mp_bgm;\r\n    private AudioSpectrumListener audioSpectrumListener;\r\n    \/\/ \u6587\u5b57\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u7528\u30e1\u30c3\u30b7\u30e5\u30d3\u30e5\u30fc\u914d\u5217\r\n    private MeshView[] backMesh;\r\n\r\n    @Override\r\n    public void start(Stage primaryStage) {\r\n        Group root = new Group();\r\n        Label translateLabel = new Label(\"Translate\");\r\n        Label xLabel = new Label(\"X\");\r\n        Label yLabel = new Label(\"Y\");\r\n        Label zLabel = new Label(\"Z\");\r\n        Label scaleLabel = new Label(\"Scale      \"); \/\/ \u826f\u3044\u5b50\u306f\u3053\u3093\u306a\u3053\u3068\u3057\u3061\u3083\u3060\u3081\u3088\uff01\r\n        Label sxLabel = new Label(\"X\");\r\n        Label syLabel = new Label(\"Y\");\r\n        Label szLabel = new Label(\"Z\");\r\n        Label rotateLabel = new Label(\"Rotate    \"); \/\/ \u826f\u3044\u5b50\u306f\u3053\u3093\u306a\u3053\u3068\u3057\u3061\u3083\u3060\u3081\u3088\uff01\r\n        Label rxLabel = new Label(\"X\");\r\n        Label ryLabel = new Label(\"Y\");\r\n        Label rzLabel = new Label(\"Z\");\r\n        Label drawModeLabel = new Label(\"Wireframe\");\r\n        Label resetLabel = new Label(\"        Reset\"); \/\/ \u826f\u3044\u5b50\u306f\u3053\u3093\u306a\u3053\u3068\u3057\u3061\u3083\u3060\u3081\u3088\uff01\r\n        Label walkLabel = new Label(\"   Duke Walk!\"); \/\/ \u826f\u3044\u5b50\u306f\u3053\u3093\u306a\u3053\u3068\u3057\u3061\u3083\u3060\u3081\u3088\uff01\r\n        Label stopLabel = new Label(\"   Duke Stop!\"); \/\/ \u826f\u3044\u5b50\u306f\u3053\u3093\u306a\u3053\u3068\u3057\u3061\u3083\u3060\u3081\u3088\uff01\r\n        Slider xSlider = new Slider(-3000, 3000, 0);\r\n        Slider ySlider = new Slider(-3000, 3000, 0);\r\n        Slider zSlider = new Slider(-5000, 5000, 0);\r\n        Slider sxSlider = new Slider(0.01, 10, 1.0);\r\n        Slider sySlider = new Slider(0.01, 10, 1.0);\r\n        Slider szSlider = new Slider(0.01, 10, 1.0);\r\n        Slider rxSlider = new Slider(-360, 360, 0);\r\n        Slider rySlider = new Slider(-360, 360, 0);\r\n        Slider rzSlider = new Slider(-360, 360, 0);\r\n        xSlider.setPrefSize(533, 0);\r\n        ySlider.setPrefSize(533, 0);\r\n        zSlider.setPrefSize(533, 0);\r\n        sxSlider.setPrefSize(533, 0);\r\n        sySlider.setPrefSize(533, 0);\r\n        szSlider.setPrefSize(533, 0);\r\n        rxSlider.setPrefSize(533, 0);\r\n        rySlider.setPrefSize(533, 0);\r\n        rzSlider.setPrefSize(533, 0);\r\n        xSlider.setShowTickLabels(true);\r\n        xSlider.setMajorTickUnit(500);\r\n        ySlider.setShowTickLabels(true);\r\n        ySlider.setMajorTickUnit(500);\r\n        zSlider.setShowTickLabels(true);\r\n        zSlider.setMajorTickUnit(500);\r\n        sxSlider.setShowTickLabels(true);\r\n        sxSlider.setMajorTickUnit(2.0);\r\n        sySlider.setShowTickLabels(true);\r\n        sySlider.setMajorTickUnit(2.0);\r\n        szSlider.setShowTickLabels(true);\r\n        szSlider.setMajorTickUnit(2.0);\r\n        rxSlider.setShowTickLabels(true);\r\n        rxSlider.setMajorTickUnit(90);\r\n        rySlider.setShowTickLabels(true);\r\n        rySlider.setMajorTickUnit(90);\r\n        rzSlider.setShowTickLabels(true);\r\n        rzSlider.setMajorTickUnit(90);\r\n\r\n        CheckBox meshCheckBox = new CheckBox(\"Wireframe\");\r\n\r\n        Button resetBtn = new Button();\r\n        resetBtn.setText(\"Reset\");\r\n\r\n        Button walkBtn = new Button();\r\n        walkBtn.setText(\"Walk!\");\r\n\r\n        Button stopBtn = new Button();\r\n        stopBtn.setText(\"Stop!\");\r\n\r\n        final Accordion accordion = new Accordion();\r\n        final TitledPane translatePane = new TitledPane(\"Camera Translate\", new HBox(30, translateLabel, xLabel, xSlider, yLabel, ySlider, zLabel, zSlider));\r\n        final TitledPane scalePane = new TitledPane(\"Camera Scale\", new HBox(30, scaleLabel, sxLabel, sxSlider, syLabel, sySlider, szLabel, szSlider));\r\n        final TitledPane rotatePane = new TitledPane(\"Camera Rotate\", new HBox(30, rotateLabel, rxLabel, rxSlider, ryLabel, rySlider, rzLabel, rzSlider));\r\n        final TitledPane drawModePane = new TitledPane(\"DrawMode & Reset & Duke Walk!\", new HBox(20, drawModeLabel, meshCheckBox, resetLabel, resetBtn, walkLabel, walkBtn, stopLabel, stopBtn));\r\n\r\n        translatePane.setAnimated(true);\r\n        scalePane.setAnimated(true);\r\n        rotatePane.setAnimated(true);\r\n        drawModePane.setAnimated(true);\r\n\r\n        accordion.getPanes().addAll(translatePane, scalePane, rotatePane, drawModePane);\r\n        accordion.setExpandedPane(translatePane);\r\n\r\n        root.getChildren().add(accordion);\r\n\r\n        accordion.setLayoutX(17);\r\n        accordion.setLayoutY(873);\r\n\r\n        Scene scene = new Scene(root, 1910, 1020, true);\r\n        scene.setFill(Color.PINK);\r\n\r\n        PerspectiveCamera cam = new PerspectiveCamera(false);\r\n        scene.setCamera(cam);\r\n\r\n        root.getChildren().add(cam);\r\n\r\n        \/\/ \u30b5\u30d6\u30b7\u30fc\u30f3\u7528\u306e\u30b5\u30d6\u30ab\u30e1\u30e9\r\n        PerspectiveCamera 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        AnchorPane subRoot = new AnchorPane();\r\n        subRoot.setBackground(Background.EMPTY);\r\n\r\n        Group allGroup = new Group();\r\n\r\n        \/\/ 3D \u30e2\u30c7\u30eb\u3092\u30a4\u30f3\u30dd\u30fc\u30c8\r\n        \/\/ Duke\r\n        ObjModelImporter dukeImporter = new ObjModelImporter();\r\n        \/\/ Bord\r\n        ObjModelImporter baseImporter = new ObjModelImporter();\r\n        \/\/ \u6587\u5b57\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\r\n        ObjModelImporter backImporter = new ObjModelImporter();\r\n\r\n        try {\r\n            URL objUrl = this.getClass().getResource(\"Duke\/duke.obj\");\r\n            dukeImporter.read(objUrl);\r\n        } catch (ImportException e) {\r\n            \/\/ G'catch! :p\r\n            e.printStackTrace();\r\n            return;\r\n        }\r\n\r\n        MeshView[] dukeMesh = dukeImporter.getImport();\r\n\r\n        dukeImporter.close();\r\n\r\n        Group dukeGroup = new Group();\r\n        for (MeshView _dukeMesh : dukeMesh) {\r\n            dukeGroup.getChildren().addAll(_dukeMesh);\r\n            _dukeMesh.drawModeProperty().bind(new When(showWireframe).then(DrawMode.LINE).otherwise(DrawMode.FILL));\r\n        }\r\n\r\n        try {\r\n            URL objUrl = this.getClass().getResource(\"Duke_base\/base.obj\");\r\n            baseImporter.read(objUrl);\r\n        } catch (ImportException e) {\r\n            \/\/ G'catch! :p\r\n            e.printStackTrace();\r\n            return;\r\n        }\r\n\r\n        MeshView[] baseMesh = baseImporter.getImport();\r\n\r\n        baseImporter.close();\r\n\r\n        Group baseGroup = new Group();\r\n        for (MeshView _baseMesh : baseMesh) {\r\n            baseGroup.getChildren().addAll(_baseMesh);\r\n            _baseMesh.drawModeProperty().bind(new When(showWireframe).then(DrawMode.LINE).otherwise(DrawMode.FILL));\r\n        }\r\n\r\n        try {\r\n            URL objUrl = this.getClass().getResource(\"back_duke\/back_duke.obj\");\r\n            backImporter.read(objUrl);\r\n        } catch (ImportException e) {\r\n            \/\/ G'catch! :p\r\n            e.printStackTrace();\r\n            return;\r\n        }\r\n\r\n        backMesh = backImporter.getImport();\r\n\r\n        backImporter.close();\r\n\r\n        Group backGroup = new Group();\r\n        for (MeshView _backMesh : backMesh) {\r\n            backGroup.getChildren().addAll(_backMesh);\r\n            _backMesh.drawModeProperty().bind(new When(showWireframe).then(DrawMode.LINE).otherwise(DrawMode.FILL));\r\n        }\r\n\r\n        allGroup.getChildren().addAll(dukeGroup, baseGroup, backGroup);\r\n\r\n        \/\/ Duke \u6b69\u884c\u30bf\u30fc\u30cb\u30f3\u30b0\u30dd\u30a4\u30f3\u30c8\r\n        \/\/ \u30aa\u30d5\u30bb\u30c3\u30c8\u30de\u30fc\u30b8\u30f3 \uff08\u9069\u5f53\u306b\u8a2d\u5b9a\uff09\r\n        int offsetMargin = (int) (dukeGroup.getLayoutBounds().getDepth() \/ 6);\r\n        \/\/ \u30bf\u30fc\u30cb\u30f3\u30b0\u30dd\u30a4\u30f3\u30c8 -Z\r\n        int bordTurnPoint = (int) (baseGroup.getLayoutBounds().getMinZ() - dukeGroup.getLayoutBounds().getMinZ());\r\n        \/\/ \u30bf\u30fc\u30cb\u30f3\u30b0\u30dd\u30a4\u30f3\u30c8 +Z\r\n        int bordEndPoint = (int) (baseGroup.getLayoutBounds().getMaxZ() - dukeGroup.getLayoutBounds().getDepth() \/ 2 - offsetMargin);\r\n\r\n        \/\/ \u30dc\u30fc\u30c9\u3092\u975e\u8868\u793a\r\n        baseGroup.setVisible(false);\r\n        \/\/ \u6587\u5b57\u3092\u975e\u8868\u793a\r\n        backGroup.setVisible(false);\r\n\r\n        \/\/ \u74b0\u5883\u5149\u8a2d\u5b9a\r\n        AmbientLight ambient = new AmbientLight();\r\n        ambient.setColor(Color.rgb(150, 150, 150, 0.6));\r\n        ambient.getScope().addAll(allGroup);\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(-700);\r\n        point.setLayoutY(-1_000);\r\n        point.setTranslateZ(-1_200);\r\n        point.getScope().addAll(allGroup);\r\n\r\n        subRoot.getChildren().addAll(allGroup, subCam, ambient, point);\r\n\r\n        \/\/ Create SubScene\r\n        SubScene subScene = new SubScene(subRoot, 1920, 860, true, SceneAntialiasing.BALANCED);\r\n        subScene.setFill(Color.ALICEBLUE);\r\n        subScene.setCamera(subCam);\r\n\r\n        root.getChildren().addAll(subScene);\r\n\r\n        \/\/ \u30de\u30a6\u30b9\u3067\u30e2\u30c7\u30eb\u64cd\u4f5c\u7528\r\n        Rotate xRotate;\r\n        Rotate yRotate;\r\n        allGroup.getTransforms().setAll(\r\n                xRotate = new Rotate(0, Rotate.X_AXIS),\r\n                yRotate = new Rotate(0, Rotate.Y_AXIS)\r\n        );\r\n        xRotate.angleProperty().bind(angleX);\r\n        yRotate.angleProperty().bind(angleY);\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        subScene.setOnMouseDragged(event -> {\r\n            angleX.set(anchorAngleX - (anchorY - event.getSceneY()));\r\n            angleY.set(anchorAngleY + anchorX - event.getSceneX());\r\n        });\r\n\r\n        \/\/ \u30b5\u30d6\u30ab\u30e1\u30e9\u64cd\u4f5c\u7528\r\n        \/\/ \u79fb\u52d5\r\n        xSlider.valueProperty().bindBidirectional(xPos);\r\n        subCam.translateXProperty().bind(xPos);\r\n        ySlider.valueProperty().bindBidirectional(yPos);\r\n        subCam.translateYProperty().bind(yPos);\r\n        zSlider.valueProperty().bindBidirectional(zPos);\r\n        subCam.translateZProperty().bind(zPos);\r\n        \/\/ \u62e1\u5927\u7e2e\u5c0f\r\n        sxSlider.valueProperty().bindBidirectional(sxPos);\r\n        subCam.scaleXProperty().bind(sxPos);\r\n        sySlider.valueProperty().bindBidirectional(syPos);\r\n        subCam.scaleYProperty().bind(syPos);\r\n        szSlider.valueProperty().bindBidirectional(szPos);\r\n        subCam.scaleZProperty().bind(szPos);\r\n        \/\/ \u56de\u8ee2\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        rxSlider.valueProperty().bindBidirectional(rxPos);\r\n        rySlider.valueProperty().bindBidirectional(ryPos);\r\n        rzSlider.valueProperty().bindBidirectional(rzPos);\r\n\r\n        \/\/ Duke \u30bf\u30fc\u30f3\u7528\r\n        Rotate tyRotate;\r\n        dukeGroup.getTransforms().setAll(\r\n                tyRotate = new Rotate(0, Rotate.Y_AXIS)\r\n        );\r\n        tyRotate.angleProperty().bind(turnAngleY);\r\n\r\n        \/\/ \u8868\u793a\u30e2\u30fc\u30c9\r\n        meshCheckBox.selectedProperty().bindBidirectional(showWireframe);\r\n\r\n        \/\/ \u30ea\u30bb\u30c3\u30c8\r\n        resetBtn.setOnAction((ActionEvent event) -> {\r\n            \/\/ Icon \u5909\u66f4\r\n            Image myIcon = new Image(this.getClass().getResource(\"icon\/duke_3.png\").toString());\r\n            primaryStage.getIcons().add(myIcon);\r\n\r\n            \/\/ \u97f3\u697d\u505c\u6b62\r\n            if (mp_bgm != null) {\r\n                mp_bgm.stop();\r\n            }\r\n\r\n            if (walkTimer != null || dukeAnim != null) {\r\n                dukeAnim.stop();\r\n                walkTimer.stop();\r\n                if (leftTurn != null) {\r\n                    leftTurn.stop();\r\n                }\r\n                if (rightTurn != null) {\r\n                    rightTurn.stop();\r\n                }\r\n            }\r\n\r\n            \/\/ \u30dc\u30fc\u30c9\u975e\u8868\u793a\r\n            baseGroup.setVisible(false);\r\n            \/\/ \u6587\u5b57\u3092\u975e\u8868\u793a\r\n            backGroup.setVisible(false);\r\n            \/\/ Duke \u306e\u4f4d\u7f6e\u3092\u521d\u671f\u5316\r\n            dukeGroup.setTranslateZ(0);\r\n            \/\/ Duke \u306e\u5411\u304d\u3092\u521d\u671f\u5316\r\n            turnAngleY.set(0);\r\n\r\n            \/\/ \u8a2d\u5b9a\u521d\u671f\u5316\r\n            xPos.set(0);\r\n            yPos.set(0);\r\n            zPos.set(-1_000);\r\n\r\n            angleWalk_r_X.set(0);\r\n            angleWalk_l_X.set(0);\r\n            angleWalk_l_arm.set(0);\r\n            angleWalk_r_arm.set(0);\r\n\r\n            anchorAngleX = 0;\r\n            anchorAngleY = 0;\r\n            angleX.set(0);\r\n            angleY.set(0);\r\n\r\n            sxPos.set(1.0);\r\n            syPos.set(1.0);\r\n            szPos.set(1.0);\r\n\r\n            rxPos.set(0);\r\n            ryPos.set(0);\r\n            rzPos.set(0);\r\n\r\n        });\r\n\r\n        \/\/ Duke Walk \u958b\u59cb\r\n        walkBtn.setOnAction((ActionEvent event) -> {\r\n            \/\/ Icon \u5909\u66f4\r\n            Image myIcon = new Image(this.getClass().getResource(\"icon\/duke_1.png\").toString());\r\n            primaryStage.getIcons().add(myIcon);\r\n\r\n            \/\/ \u97f3\u697d\u518d\u751f\u3001\u30b9\u30da\u30af\u30c8\u30e9\u30e0\u30ea\u30b9\u30ca\u30fc\u5b9f\u88c5\r\n            audioSpectrumListener = this;\r\n            mp_bgm = new MediaPlayer(bgm);\r\n            mp_bgm.setAudioSpectrumListener(audioSpectrumListener);\r\n            mp_bgm.setAudioSpectrumInterval(0.01);\r\n            mp_bgm.setAudioSpectrumNumBands(8);\r\n            mp_bgm.setVolume(0.9);\r\n            mp_bgm.setAutoPlay(true);\r\n            mp_bgm.setCycleCount(MediaPlayer.INDEFINITE);\r\n\r\n            \/\/ \u30dc\u30fc\u30c9\u3092\u8868\u793a\r\n            baseGroup.setVisible(true);\r\n            \/\/ \u6587\u5b57\u3092\u8868\u793a\r\n            backGroup.setVisible(true);\r\n            \/\/ Duke \u306e\u4f4d\u7f6e\u3092\u521d\u671f\u5316\r\n            dukeGroup.setTranslateZ(0);\r\n            \/\/ Duke \u306e\u5411\u304d\u3092\u521d\u671f\u5316\r\n            turnAngleY.set(0);\r\n\r\n            \/\/ \u8a2d\u5b9a\u521d\u671f\u5316\r\n            azimuth = 0;\r\n            previousHandledTime = 0L;\r\n\r\n            anchorAngleX = 0;\r\n            anchorAngleY = 0;\r\n            angleX.set(0);\r\n            angleY.set(0);\r\n\r\n            xPos.set(0);\r\n            yPos.set(0);\r\n            zPos.set(-1_200);\r\n\r\n            sxPos.set(1.0);\r\n            syPos.set(1.0);\r\n            szPos.set(1.0);\r\n\r\n            rxPos.set(0);\r\n            ryPos.set(0);\r\n            rzPos.set(0);\r\n\r\n            \/\/ Duke \u30e2\u30c7\u30eb\u624b\u8db3\u52d5\u4f5c\u7528\r\n            Rotate r_legRotate;\r\n            Rotate l_legRotate;\r\n            Rotate r_armRotate;\r\n            Rotate l_armRotate;\r\n\r\n            dukeMesh[2].getTransforms().setAll(\r\n                    r_legRotate = new Rotate(0, Rotate.X_AXIS));\r\n            dukeMesh[3].getTransforms().setAll(\r\n                    l_legRotate = new Rotate(0, Rotate.X_AXIS));\r\n            dukeMesh[4].getTransforms().setAll(\r\n                    r_armRotate = new Rotate(0, Rotate.Z_AXIS));\r\n            dukeMesh[5].getTransforms().setAll(\r\n                    l_armRotate = new Rotate(0, Rotate.X_AXIS));\r\n\r\n            r_legRotate.angleProperty().bind(angleWalk_r_X);\r\n            l_legRotate.angleProperty().bind(angleWalk_l_X);\r\n            l_armRotate.angleProperty().bind(angleWalk_l_arm);\r\n            r_armRotate.angleProperty().bind(angleWalk_r_arm);\r\n\r\n            \/\/ \u6b69\u884c\u30e2\u30fc\u30b7\u30e7\u30f3\r\n            dukeAnim = new Timeline(\r\n                    new KeyFrame(\r\n                            new Duration(500),\r\n                            new KeyValue(angleWalk_r_X, -25),\r\n                            new KeyValue(angleWalk_l_X, 25),\r\n                            new KeyValue(angleWalk_l_arm, -20),\r\n                            new KeyValue(angleWalk_r_arm, 12, Interpolator.EASE_BOTH)\r\n                    ),\r\n                    new KeyFrame(\r\n                            new Duration(1_000),\r\n                            new KeyValue(angleWalk_r_X, 0),\r\n                            new KeyValue(angleWalk_l_X, 0),\r\n                            new KeyValue(angleWalk_l_arm, 0),\r\n                            new KeyValue(angleWalk_r_arm, 0, Interpolator.EASE_BOTH)\r\n                    ),\r\n                    new KeyFrame(\r\n                            new Duration(1_500),\r\n                            new KeyValue(angleWalk_r_X, 25),\r\n                            new KeyValue(angleWalk_l_X, -25),\r\n                            new KeyValue(angleWalk_l_arm, 20),\r\n                            new KeyValue(angleWalk_r_arm, 12, Interpolator.EASE_BOTH)\r\n                    ),\r\n                    new KeyFrame(\r\n                            new Duration(2_000),\r\n                            new KeyValue(angleWalk_r_X, 0),\r\n                            new KeyValue(angleWalk_l_X, 0),\r\n                            new KeyValue(angleWalk_l_arm, 0),\r\n                            new KeyValue(angleWalk_r_arm, 0, Interpolator.EASE_BOTH)\r\n                    )\r\n            );\r\n\r\n            dukeAnim.setCycleCount(Timeline.INDEFINITE);\r\n            dukeAnim.play();\r\n\r\n            \/\/ \u6b69\u884c\r\n            walkTimer = new AnimationTimer() {\r\n                @Override\r\n                public void handle(long now) {\r\n                    update(now);\r\n                }\r\n\r\n                private void update(long now) {\r\n                    if (previousHandledTime == 0) {\r\n                        previousHandledTime = now;\r\n                        return;\r\n                    }\r\n                    \/\/ \u30b5\u30d6\u30ab\u30e1\u30e9\u3092\u534a\u5f84 SUBCAMERA_RADIUS \u306e\u5186\u306e\u4e2d\u5fc3\u3080\u3051\u3066\u56de\u8ee2\u64ae\u5f71\u3059\u308b\u3002\r\n                    azimuth += azimuthRateProperty.get() * (now - previousHandledTime) \/ 1_000_000_000;\r\n                    previousHandledTime = now;\r\n                    xPos.set(Math.sin(Math.toRadians(azimuth)) * SUBCAMERA_RADIUS);\r\n                    zPos.set(-1 * Math.cos(Math.toRadians(azimuth)) * SUBCAMERA_RADIUS);\r\n                    yPos.set(-1 * Math.sin(Math.toRadians(elevationProperty.getValue())) * SUBCAMERA_RADIUS);\r\n                    ryPos.set(-1 * azimuth);\r\n\r\n                    \/\/ \u6b69\u884c\u5236\u5fa1\r\n                    if (dukeGroup.getTranslateZ() > bordTurnPoint && turnAngleY.get() == 0) {\r\n                        dukeGroup.setTranslateZ(dukeGroup.getTranslateZ() + -5);\r\n                        if (dukeGroup.getTranslateZ() < bordTurnPoint + 1) {\r\n                            rightTurn();\r\n                        }\r\n                    }\r\n\r\n                    \/\/ \u6b69\u884c\u5236\u5fa1\r\n                    if (dukeGroup.getTranslateZ() < bordEndPoint &#038;&#038; turnAngleY.get() == 180) {\r\n                        dukeGroup.setTranslateZ(dukeGroup.getTranslateZ() + 5);\r\n                        if (dukeGroup.getTranslateZ() > bordEndPoint - 1) {\r\n                            leftTurn();\r\n                        }\r\n                    }\r\n\r\n                }\r\n\r\n                \/\/ \u6b69\u884c\u53f3\u53cd\u8ee2\u51e6\u7406\r\n                private void rightTurn() {\r\n                    rightTurn = new Timeline(\r\n                            new KeyFrame(\r\n                                    new Duration(700),\r\n                                    new KeyValue(turnAngleY, 180, Interpolator.EASE_BOTH)\r\n                            ));\r\n                    rightTurn.play();\r\n                }\r\n\r\n                \/\/ \u6b69\u884c\u5de6\u53cd\u8ee2\u51e6\u7406\r\n                private void leftTurn() {\r\n                    leftTurn = new Timeline(\r\n                            new KeyFrame(\r\n                                    new Duration(700),\r\n                                    new KeyValue(turnAngleY, 0, Interpolator.EASE_BOTH)\r\n                            ));\r\n                    leftTurn.play();\r\n                }\r\n            };\r\n            walkTimer.start();\r\n        });\r\n\r\n        \/\/ \u6b69\u884c\u30b9\u30c8\u30c3\u30d7\r\n        stopBtn.setOnAction((ActionEvent event) -> {\r\n            \/\/ Icon \u5909\u66f4\r\n            Image myIcon = new Image(this.getClass().getResource(\"icon\/duke_2.png\").toString());\r\n            primaryStage.getIcons().add(myIcon);\r\n\r\n            \/\/ \u97f3\u697d\u505c\u6b62\r\n            if (mp_bgm != null) {\r\n                mp_bgm.stop();\r\n            }\r\n\r\n            if (walkTimer != null || dukeAnim != null) {\r\n                dukeAnim.stop();\r\n                walkTimer.stop();\r\n                if (leftTurn != null) {\r\n                    leftTurn.stop();\r\n                }\r\n                if (rightTurn != null) {\r\n                    rightTurn.stop();\r\n                }\r\n            }\r\n\r\n        });\r\n\r\n        \/\/ Icon \u8a2d\u5b9a\r\n        Image myIcon = new Image(this.getClass().getResource(\"icon\/cludia_icon.png\").toString());\r\n        primaryStage.getIcons().add(myIcon);\r\n        primaryStage.setTitle(\"Duke Walk\");\r\n        primaryStage.setScene(scene);\r\n        primaryStage.setResizable(false);\r\n        primaryStage.show();\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        launch(args);\r\n    }\r\n\r\n    @Override\r\n    public void spectrumDataUpdate(double timestamp, double duration, float[] magnitudes, float[] phases) {\r\n        \/\/ \u30d0\u30c3\u30af\u306e\u6587\u5b57\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u30b9\u30b1\u30fc\u30ea\u30f3\u30b0\r\n        IntStream.range(0, magnitudes.length).forEach(i -> {\r\n            backMesh[i].setScaleX((magnitudes[i] + 60.01) * 0.1 + 1.0);\r\n            backMesh[i].setScaleY((magnitudes[i] + 60.01) * 0.1 + 1.0);\r\n            backMesh[i].setScaleZ((magnitudes[i] + 60.01) * 0.1 + 1.0);\r\n        });\r\n    }\r\n\r\n}\r\n\r\n<\/pre>\n<\/p>\n<p>&nbsp;<\/p>\n<div id=\"scid:0767317B-992E-4b12-91E0-4F059A8CECA8:0a5423af-a87c-4bf5-bf48-ceb8c0f4bdb0\" class=\"wlWriterEditableSmartContent\" style=\"float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px\">Hatena \u30bf\u30b0: <a href=\"http:\/\/b.hatena.ne.jp\/t\/JavaFX\" rel=\"tag\">JavaFX<\/a><\/div>\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%3D1375&title=Duke%20%E3%82%92%E6%AD%A9%E3%81%8B%E3%81%9B%E3%81%A6%E3%81%BF%E3%81%9F%E3%80%82%20JavaFX%203D%20%E3%82%A2%E3%83%8B%E3%83%A1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3' 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%3D1375&t=Duke%20%E3%82%92%E6%AD%A9%E3%81%8B%E3%81%9B%E3%81%A6%E3%81%BF%E3%81%9F%E3%80%82%20JavaFX%203D%20%E3%82%A2%E3%83%8B%E3%83%A1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3' 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=1375\" ><\/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=1375\" data-text=\"Duke \u3092\u6b69\u304b\u305b\u3066\u307f\u305f\u3002 JavaFX 3D \u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\" data-lang=\"ja\">Tweet<\/a><\/div>\n    <\/div>\n<br class='wp_social_bookmarking_light_clear' \/>\n","protected":false},"excerpt":{"rendered":"<p>\u4eca\u5e74\u306e JavaOne \u3067\u30c1\u30a7\u30b9\u306e\u99d2\u306b\u626e\u3057\u305f Duke \u304c\u683c\u597d\u826f\u304f\u6b69\u3044\u3066\u3044\u305f\u3002 JavaFX 3D \u30c6\u30af\u30ce\u30ed\u30b8\u30fc\u3092\u99c6\u4f7f\u3057\u305f\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u304c\u62ab\u9732\u3055\u308c\u3066\u4f1a\u5834\u3092\u308f\u304b\u305b\u3066\u3044\u305f\u3002 \u3068\u3066\u3082\u7d20\u6575\u3060\u3063\u305f\u304c Maya \u3068\u8a00\u3046\u9ad8\u4fa1\u306a 3DCG \u30bd\u30d5\u30c8\u3068 3DViewer \uff08\u4f55\u6545\u304b\u4eca\u306f\u52d5\u304b\u306a\u3044\u3089\u3057\u3044\uff09\u3092\u4f7f\u3063\u3066\u4f5c\u3089\u308c\u3066\u3044\u308b\u3089\u3057\u3044\u3002\uff08\u672a\u78ba\u8a8d\u3067\u3059\u3002\uff09 \u30cd\u30c3\u30c8\u4e0a\u306b\u3082 3D \u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u4f5c\u6210\u306e\u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb\u3084\u30b5\u30f3\u30d7\u30eb\u3082\u307e\u3060\u898b\u5f53\u305f\u3089\u306a\u3044\u3002 \u3068\u306f\u8a00\u3048\u3001JavaFX 8 \u306b\u306f\u6a19\u6e96\u3067 3DAPI \u304c\u5b9f\u88c5\u3055\u308c\u3066\u3044\u308b\u306e\u3067\u8fd1\u3044\u5c06\u6765\u76ee\u306b\u3059\u308b\u3053\u3068\u3082\u3042\u308b\u3060\u308d\u3046\u3002 \u3067\u3082\u3001\u65b0\u3057\u3044\u7269\u597d\u304d\u306e\u79c1\u306f\u5f85\u3061\u304d\u308c\u306a\u3044\u306e\u3067\u624b\u63a2\u308a\u3067\u30b0\u30ea\u30b0\u30ea\u3057\u3066\u307f\u305f\u3002 \u65e5\u672c\u8a9e\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-1375","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\/1375","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=1375"}],"version-history":[{"count":3,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1375\/revisions"}],"predecessor-version":[{"id":1379,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1375\/revisions\/1379"}],"wp:attachment":[{"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1375"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1375"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1375"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}