ThreeJSでHSP3オフィシャル3D素材「珠音」を表示させて走らせてみます。
VIDEO
ThreeJSを使えば3Dオブジェクトを描画することができます。ただこれまでは自作したヘンテコな物体の描画しかしてきませんでした。やるならモデルデータの読み込みをしてみたいものです。
人間の形をしていて動作させることができるものはないかと探していたら、こんなものをみつけました。
HSP3オフィシャル3D素材 珠音(たまね)
珠音(たまね)は、Hot Soup Processor(HSP)とともに使用することのできる 3Dサンプル素材です。HSP3の3D描画ライブラリであるHGIMG3/HGIMG4により表示可能なデータとスクリプト、及び元データがすべて収められています。
HSP3はここからダウンロードできます。
HSP3.7β2を公開しました
解凍したあとhsp37beta\sample\hgimg4\fbxのなかにhigh_school_girl.fbxがあります。これをつかいましょう。
最初にhigh_school_girl.fbxをダブルクリックすると3Dビューアが起動します。
まず3Dビューアのメニューからファイル ⇒ 名前をつけて保存を選択します。そしてファイル形式はGLTFバイナリを指定して保存します。GLTF形式に変換する理由は鳩でもわかるC#管理人がfbxで3Dオブジェクトを描画する方法を知らないのと、GLTF形式に変換することでfbxファイルがあったフォルダのなかのtgaファイルがなくても動作させることができるからです。ファイルはひとつにまとめてしまいましょう。
ではさっそくコードを示します。まずはHTML部分です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
< ! DOCTYPE html >
< html lang ="ja" >
< head >
< meta charset ="UTF-8" >
< title > ThreeJS で珠音ちゃんを走らせてみる< /title >
< meta http -equiv ="X-UA-Compatible" content ="IE=edge" >
< meta name ="viewport" content ="width=device-width, initial-scale=1.0" >
< meta name ="description" content ="ThreeJSで珠音ちゃんを走らせてみる" />
< /head >
< body >
< canvas id ="canvas" > < /canvas >
<script src ="https://unpkg.com/three@0.140.2/build/three.min.js" > </script>
<script src ="https://unpkg.com/three@0.137.4/examples/js/loaders/GLTFLoader.js" > </script>
<script src ="./index.js" > </script>
< /body >
< /html >
JavaScript部分を示します。
ページが読み込まれたらinit関数が実行されます。
ここではレンダラー、シーン、カメラを作成したあと、シーンにライトを追加しています。そのあと後述するLoadedGltf関数を呼び出してGLTF形式のモデルデータを読み込んで3Dオブジェクトをシーンに追加しています。
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// ページの読み込みを待つ
window . addEventListener ( 'DOMContentLoaded' , init ) ;
let mixer ;
let clock = new THREE . Clock ( ) ;
let tamane_gltf ;
function init ( ) {
// レンダラーを作成
renderer = new THREE . WebGLRenderer ( {
canvas : document . querySelector ( "#canvas" )
} ) ;
// 幅、高さ
let width = 600 ;
let height = 500 ;
renderer . setPixelRatio ( 1 ) ;
renderer . setSize ( width , height ) ;
// シーンを作成
scene = new THREE . Scene ( ) ;
// カメラを作成
camera = new THREE . PerspectiveCamera ( 45 , width / height , 1 , 10000 ) ;
camera . position . set ( 0 , 0 , 500 ) ;
camera . lookAt ( new THREE . Vector3 ( 0 , 50 , 0 ) ) ;
// 平行光源
const light = new THREE . DirectionalLight ( 0xffffff ) ;
light . intensity = 2 ; // 光の強さを倍に
light . position . set ( 0 , 0 , 1 ) ;
scene . add ( light ) ;
// GLTF形式のモデルデータを読み込む
const loader = new THREE . GLTFLoader ( ) ;
const buildingUrl = "./high_school_girl.glb" ;
loader . load ( buildingUrl , LoadedGltf ) ; // 第二引数はコールバック関数(後述)
renderer . gammaOutput = true ;
renderer . gammaFactor = 2.2 ;
tick ( ) ; // 後述
}
GLTF形式のモデルデータを読み込んで3Dオブジェクトをシーンに追加するLoadedGltf関数を示します。
GLTFファイルにはシーンの情報の他にさまざまな情報が含まれます。そのため、コールバック関数の引数からシーンの情報だけ抜き出して追加します。さらにアニメーションさせる処理も追加します。
珠音のアニメーションには「停止」「歩く」「走る」の3種類が用意されています。最初は停止状態にしておきます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function LoadedGltf ( gltf ) {
tamane_gltf = gltf ;
const model = gltf . scene ;
model . scale . set ( 1.0 , 1.0 , 1.0 ) ;
model . position . set ( 0 , -100 , 0 ) ;
model . position . set ( 0 , -100 , 0 ) ;
scene . add ( model ) ;
const animations = gltf . animations ;
if ( animations && animations.length) {
mixer = new THREE.AnimationMixer(model);
let animation = animations [ 0 ] ;
let action = mixer . clipAction ( animation ) ; // Animation Actionを生成
action . clampWhenFinished = true ; // アニメーションの最後のフレームでアニメーションが終了
action . play ( ) ; // アニメーションを再生
}
}
アニメーションを更新し、レンダラーを呼び出す処理を示します。
function tick ( ) {
renderer . render ( scene , camera ) ;
requestAnimationFrame ( tick ) ;
//Animation Mixerを実行
if ( mixer ) {
mixer . update ( clock . getDelta ( ) ) ;
}
}
これだけでは面白くないのでキー操作をすると方向を変えたり、走ったり止まったりするようにしてみます。左右のキーで方向転換して(向かい合っている状態では左右が入れ替わっているので違和感あるかも)、↑キーで走り出し↓キーで止まります。いきなり止まるとおかしいので0.25秒間歩かせてから止まります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
document . onkeydown = ( e ) => {
const model = tamane_gltf . scene ;
if ( e . key == 'ArrowRight' )
model . rotation . y -= 0.05 ;
if ( e . key == 'ArrowLeft' )
model . rotation . y += 0.05 ;
if ( e . key == 'ArrowUp' )
Run ( ) ;
if ( e . key == 'ArrowDown' )
Stop ( ) ;
}
function Run ( ) {
const model = tamane_gltf . scene ;
const animations = tamane_gltf . animations ;
mixer = new THREE . AnimationMixer ( model ) ;
let animation = animations [ 2 ] ; // animations[2]は走る動作
let action = mixer . clipAction ( animation ) ;
action . clampWhenFinished = true ;
action . play ( ) ;
}
function Stop ( ) {
const model = tamane_gltf . scene ;
const animations = tamane_gltf . animations ;
mixer = new THREE . AnimationMixer ( model ) ;
let animation = animations [ 1 ] ; // animations[1]は歩く動作
let action = mixer . clipAction ( animation ) ;
action . clampWhenFinished = true ;
action . play ( ) ;
setTimeout ( ( ) => {
mixer = new THREE . AnimationMixer ( model ) ;
let animation = animations [ 0 ] ; // animations[0]は停止している動作
let action = mixer . clipAction ( animation ) ;
action . clampWhenFinished = true ;
action . play ( ) ;
} , 250 ) ;
}
VIDEO
鳩でも分かるC#管理人からのお願い
できる仕事であれば請け負います。鳩でもわかるC#管理人はクラウドワークスに在宅ワーカーとして登録しています。お仕事の依頼もお待ちしております。
⇒ 仕事を依頼する
コメントについて
コメントで英語などの外国語でコメントをされる方がいますが、管理人は日本語以外はわからないので基本的に内容が理解できず、承認することもありません。それからへんな薬を売っているサイトやリンク先のサイトが存在しないというスパムコメントも多々あります。
Some people make comments in foreign languages such as English, but since the manager does not understand anything other than Japanese, he basically cannot understand the content and does not approve it. Please use Japanese when making comments.
そんななか日本語のコメントもいただけるようになりました。「○○という変数はどこで宣言されているのか?」「××というメソッドはどこにあるのか」「例外が発生する」「いっそのことソース丸ごとくれ」という質問ですが、管理人としては嬉しく思います。「自分が書いた記事は読まれているんだな」と。疑問点には可能な限り答えます。記事に問題があれば修正いたします。
そのうえでお願いがあります。「匿名」という味も素っ気もない名前ではなく、捨てハンでいいのでなにかハンドルネームをつくってほしいと思います。
管理人のモチベーションアップのために
よろしければご支援お願いします。
⇒ 管理人の物乞いリスト