LuaJITでお手軽3Dプログラミング (5) (2014/03/31, 2017/12/24)

LjES ver.2.01 について

English

「LuaJITでお手軽3Dプログラミング (1)(2)(3)(4)」で使っている Raspberry Pi 専用の3DライブラリLjES ですが、機能を追加して LjES ver.2.01 として公開します。前バージョン(ljes-1.00)では、球とか立方体といった形状以外は扱いにくかったので、Blender で作成して Collada 形式でエクスポートした3Dモデルを読み込む機能を追加しました。また、3Dモデルの内部に骨(ボーン)を埋め込んで変形する機能 (Skeletal Animation、Bone Animation) もサポートしました。これまでの「LuaJITでお手軽3Dプログラミング (1)(2)(3)(4)」のサンプルは修正の必要はありません。

LjES ver.2.00 は Raspbian Jessie以前用です

Blender(ブレンダー)は、3次元コンピュータグラフィックスを作成する非常に高機能のソフトウェアで、モデリング(3Dモデルの作成)、レンダリング(画像の生成)、アニメーション、ゲームエンジンとしての機能も備える無料(オープンソース)で使用できます。サポートされているプラットフォームは Windows、Linux, MacOSX などでほとんどのコンピュータで使用できます。

LjESは、LuaJIT という非常に高速なスクリプト言語を使って、 3Dアニメーションのプログラミング経験がなくても3Dプログラミングを手軽に楽しめることを目的としています。 Raspberry Pi の公式ディスクイメージの Raspbian には最初から LuaJIT が入っているため、新たに何もインストールする必要もなくプログラミングを始められます。 サンプルプログラムを試すには LjESを解凍したディレクトリでデモのスクリプトを実行するだけです。

hand.lua


demo_spheres.lua



LjES のダウンロードと使い方

LjES はいくつかの画像ファイルとテキストだけが含まれています。テキストの多くはLua言語のソースプログラムで、Raspberry Piでそのまま実行できます。

ljes-2.01.tar.gz (514KB)
GitHub (https://github.com/jun-mizutani/ljes.git )

適当なディレクトリで次のコマンドを実行すると、LjESのダウンロードと展開、デモの実行まで行います。

  curl -O https://www.mztn.org/rpi/ljes-2.01.tar.gz
  tar zxf ljes-2.01.tar.gz
  cd ljes-2.01
  cd examples
  luajit hand.lua

examples ディレクトリのサンプルは [q] キーを押すか、2分程経過すると終了します。キーを押した場合の動作を下に示します。

キー 動作
h ヘルプ
q 終了
w ノードの回転 +X
s ノードの回転 -X
a ノードの回転 +Y
d ノードの回転 -Y
z ノードの回転 +Z
x ノードの回転 -Z
e ボーンの回転 +X
r ボーンの回転 -X
y ボーンの回転 +Y
u ボーンの回転 -Y
c ボーンの回転 +Z
v ボーンの回転 -Z
o メッシュを隠す
i メッシュを表示
m メッシュの選択 (+1)
n メッシュの選択 (-1)
j ボーンの選択 (+1)
k ボーンの選択 (-1)
@ アニメーションの再生
1 指で 1 を示す
2 指で 2 を示す
3 指で 3 を示す
4 指で 4 を示す
5 手を開く
6 手を握る
9 ボーンを表示する
0 ボーンを隠す
p スクリーンショットを PNG で取得
t 描画領域を右上に
b 描画領域を右下に
g 描画領域のサイズを戻す
f フルスクリーン

LjES-2.01 の構成

LjES は大体下の図に示すような構成になっています。 図の青い部分の demo.lua はLjESの全体を使うための簡単なフレームワークになっています。グリーンの部分のbcm.lua、egl.lua、 png.lua、 gles.lua、 termios.lua は、どんな Linux のディストリビューションでも持っているシステム用の共有ライブラリ(図中の赤い部分)を LuaJIT から使うための低レベルなコードです。残りの黄色の部分は LjES のクラスライブラリ群です。 OpenGL ES2で必要となる行列演算、GPUへの転送、シェーダプログラミングといった機能や物体の形状や動作の指定、画面への文字表示といった部分を担当しています。ライトブルーのモジュールは COLLADA ファイルの読み込みとアニメーションを担当します。

クラスモジュールの依存関係とクラスの継承による階層構造です。

Colladaのアニメーションサンプル

次のコードは LjES-2 を使ってCollada形式のアニメーションを表示します。 Collada 形式は非常に自由度が高いため、LjES-2 では Blenderから Collada 形式でエクスポートしたファイルのみを対象としています。Blender 上でのメッシュは LjES の Shape に変換され、1つの Shape は最大40本のボーンを埋め込むことができます。Blender 上でメッシュとボーン(Armature)の原点(0, 0, 0)は一致させる必要があります。Rest Positionでエクスポートして下さい。

package.path = "../LjES/?.lua;" .. package.path

local demo = require("demo")
require("ColladaShape")

if arg[1] ~= nil then
  collada_file = arg[1]
else
  print("usage: luajit dae_anim0.lua your_collada.dae")
  return
end

demo.screen(0, 0)
local aSpace = demo.getSpace()
demo.backgroundColor(0.2, 0.2, 0.4)

-- load collada
local collada = ColladaShape:new()
local collada_text = util.readFile(collada_file)
collada:parse(collada_text ,true)
local shapes = collada:makeShapes(true, true)

-- set object
local node = aSpace:addNode(nil, "node")
for i = 1, #shapes do
  shapes[i]:shaderParameter("color", {0.8, 0.7, 0.6, 1.0})
  node:addShape(shapes[i])
end

-- set eye position
local eye = aSpace:addNode(nil, "eye")
local size =  demo.getShapeSize(shapes)
eye:setPosition(size.centerx, size.centery, size.max*2)

-- setup animation
node.shapes[1].anim:start()

-- call back function
function draw()
  demo.aText:writeAt(2, 24, "[q]  : quit")
  node.shapes[1].anim:play() -- play one frame of animation
  aSpace:draw(eye)
end

-- main loop
demo.loop(draw, true)
demo.exit()

Shape

回転するドーナッツを表示するアプリケーションは次に示すように 20行ほどのコードで作成することができます。 コードの赤い部分を変更すると、物体の形状や動きを変更することができます。 前バージョン(ljes-1.00)からの変更はありません。

package.path = "../LjES/?.lua;" .. package.path
local demo = require("demo")

demo.screen(0, 0)

local aSpace = demo.getSpace()

local eye = aSpace:addNode(nil, "eye")
eye:setPosition(0, 0, 30)

demo.backgroundColor(0.2, 0.2, 0.4)

local shape = Shape:new()
shape:donut(8, 3, 16, 16)
shape:endShape()
shape:shaderParameter("color", {0.5, 0.3, 0.0, 1.0})

local node = aSpace:addNode(nil, "node1")
node:setPosition(0, 0, 0)
node:addShape(shape)

function draw()
  node:rotateX(0.1)
  aSpace:draw(eye)
end

demo.loop(draw, true)
demo.exit()

この例は、[q] キーを押すか、14 分ほど経過すると終了します。 [p] キーを押すとカレントディレクトリに "ss_date_time.png" というファイル名でスクリーンショットを保存します。

コードの詳細は こちらを参照して下さい。


続く...