質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

Three.js

Three.jsはWebGLをサポートしているJavaScriptの3D描画用ライブラリです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

1回答

3662閲覧

THREE.jsの3Dアニメーションにシークバーをつけたい。youtubeのように再生位置を変更したい

univmotokazu

総合スコア17

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

Three.js

Three.jsはWebGLをサポートしているJavaScriptの3D描画用ライブラリです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2018/09/22 11:10

編集2022/01/12 10:55

前提・実現したいこと

Three.jsを用いて、3dデータ(colladaのアニメーション)にシークバーをつけて、youtubeのようにバーをいじることで再生開始位置を任意に設定できるようにしたいと考えています。

発生している問題・エラーメッセージ

下記、プログラムに示すようにTHREE.Animation.play()の引数でアニメーションのコマ画像(フレーム)を取り出せると思っているのですが、バー(seekBar)を動かしても動きがちぐはぐだし、前のフレームの画像が残ってしまいます。
また、この方法でyoutube等の動画プレイヤーのようなシークバーがつけられるか定かではないです。

該当のソースコード

javascript

1<!DOCTYPE html> 2 3<html> 4 5<head> 6 <title>Example 09.14 - Animation from collada</title> 7 <script type="text/javascript" src="threejs/libs/three.js"></script> 8 9 <script type="text/javascript" src="threejs/libs/stats.js"></script> 10 <script type="text/javascript" src="threejs/libs/dat.gui.js"></script> 11 <script type="text/javascript" src="threejs/libs/loaders/collada/Animation.js"></script> 12 <script type="text/javascript" src="threejs/libs/loaders/collada/AnimationHandler.js"></script> 13 <script type="text/javascript" src="threejs/libs/loaders/collada/KeyFrameAnimation.js"></script> 14 <script type="text/javascript" src="threejs/libs/loaders/ColladaLoader.js"></script> 15 <script type="text/javascript" src="threejs/libs/controls/OrbitControls.js"></script> 16 17 <style> 18 body { 19 /* set margin to 0 and overflow to hidden, to go fullscreen */ 20 margin: 0; 21 overflow: hidden; 22 } 23 </style> 24</head> 25 26<body> 27 28 <div id="Stats-output"> 29 </div> 30 <!-- Div which will hold the Output --> 31 <div id="WebGL-output"> 32 </div> 33 34 <!-- Javascript code that runs our Three.js examples --> 35 <script type="text/javascript"> 36 // once everything is loaded, we run our Three.js stuff. 37 function init() { 38 39 let stats = initStats(); 40 41 // create a scene, that will hold all our elements such as objects, cameras and lights. 42 let scene = new THREE.Scene(); 43 44 // create a camera, which defines where we're looking at. 45 let camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); 46 47 let orbit = new THREE.OrbitControls(camera); 48 // create a render and set the size 49 let webGLRenderer = new THREE.WebGLRenderer(); 50 webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE)); 51 webGLRenderer.setSize(window.innerWidth, window.innerHeight); 52 webGLRenderer.shadowMap.enabled = true; 53 54 // position and point the camera to the center of the scene 55 camera.position.x = 400; 56 camera.position.y = 50; 57 camera.position.z = 150; 58 camera.lookAt(new THREE.Vector3(0, 0, 0)); 59 60 61 // add spotlight for the shadows 62 let spotLight = new THREE.SpotLight(0xffffff); 63 spotLight.position.set(300, 500, 100); 64 spotLight.intensity = 3; 65 scene.add(spotLight); 66 67 // add the output of the renderer to the html element 68 document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); 69 70 // call the render function 71 let step = 0; 72 73 let clock = new THREE.Clock(); 74 75 let loader = new THREE.ColladaLoader(); 76 77 let newload = function(num) { 78 79 //daeファイルをロード 80 loader.load('threejs/assets/models/monster.dae', function(collada) { 81 82 let child = collada.skins[0]; 83 scene.add(child); 84 85 86 //let parapara = new THREE.Object3D(collada.animations[34]) 87 88 // console.log(child.geometry) 89 let animation = new THREE.Animation(child, child.geometry.animation); 90 91 animation.loop = false 92 //.playメソッドの引数でフレームを取得できる模様 93 //0で1フレーム目、-1で最後のフレームを取得できる模様。ただし、これでも逆再生はできなそう。しかし、任意のフレームを呼び出せるということなので、ここにcontrols.seek(例)を入れれば、制御できるのではなかろうか(シークバーが作れる?) 94 animation.play(num); 95 //animation.update(num) 96 97 98 // position the mesh 99 child.scale.set(0.15, 0.15, 0.15); 100 child.rotation.x = -0.5 * Math.PI; 101 child.position.x = -100; 102 child.position.y = -60; 103 }); 104 } 105 let animate = true 106 let controls = new function() { 107 this.animate = true 108 this.seekBar = 0 109 110 } 111 let gui = new dat.GUI() 112 let controller = gui.add(controls, 'seekBar', -1, 1) 113 controller.onChange(function() { 114 controls.animate = true 115 }) 116 controller.onFinishChange(function() { 117 controls.animate = false 118 }) 119 120 render(); 121 122 123 124 125 function render() { 126 127 128 stats.update(); 129 animate = controls.animate 130 //create STOP button 131 //animateがtrueのときだけ処理を実行 132 if (animate) { 133 let bar = controls.bar 134 let delta = controls.seekBar 135 //let delta = clock.getDelta(); 136 //newloadを実行し、新しいフレームと思われる画像を表示 137 newload(delta) 138 139 THREE.AnimationHandler.update(0) 140 141 } 142 orbit.update() 143 // render using requestAnimationFrame 144 requestAnimationFrame(render) 145 webGLRenderer.render(scene, camera); 146 } 147 148 function initStats() { 149 150 let stats = new Stats(); 151 stats.setMode(0); // 0: fps, 1: ms 152 153 // Align top-left 154 stats.domElement.style.position = 'absolute'; 155 stats.domElement.style.left = '0px'; 156 stats.domElement.style.top = '0px'; 157 158 document.getElementById("Stats-output").appendChild(stats.domElement); 159 160 return stats; 161 } 162 } 163 window.onload = init; 164 </script> 165</body> 166 167</html> 168

試したこと

いろいろと試したつもりですが、初学者で知識も足らず十分に方法を吟味できた、検証できたとは言えないと思っています

補足情報(FW/ツールのバージョンなど)

オライリーの初めてのThree.js第二版を使って勉強しています。

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

実行してみたわけではない(モデルファイルがない)ので、ソース上でのみ判別できたことを指摘させていただきます。

  • newload関数は、「モデルを読み込む」関数です!フレームを更新する機能をここに持たせてはダメだと思います。

 :「前のフレームの絵が残ってしまった」というより、「新しいフレームを指定した、新しいモデルがシーンに追加された」ということになります。

そのため、「loader.load」後に呼ばれる中で作っている animation をグローバルかどこかに持たせ、render のループの中では、 animation.play(num); のみ行わせる
こんな流れを組み立てられれば、少なくともモデルが複数呼ばれて前のフレームが残る、ということはなくなると思います。

  • おそらくですが、animation.play() に指定できるのは、「フレーム」ではなく、「経過秒数」の気がしました。

 :そのため、「2」を指定すると、2フレーム目ではなく、2秒後(=60フレーム後?)が表示されることになるような気がします…たぶん。

  • 残念ですが、使っているThree.jsのバージョンが、すごく古いです。

 :現在は THREE.Animationの形式は使われておらず、 THREE.AnimationMixer や AnimatinClipを使用します。 THREE.Animation 形式のサンプルやソースが、もうネット上にもほとんど残っていないかと…
ちなみに新しいアニメーションシステムの説明はこんな感じです。

なかなか険しい道かもしれませんが、頑張ってください・・・。

投稿2018/09/23 18:07

adrs2002

総合スコア203

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

univmotokazu

2018/09/24 05:30

解答いただきありがとうございます。 Three.js自体が古いバージョンなのですね... colladaファイルだと難しいのかなと今まで調べていて思ったので、モデルをgltfにして、モーフアニメーションの形で出力して再トライしてみたいと思います
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問