Skip to content

stepmania

A.C edited this page Mar 5, 2020 · 18 revisions

StepManiaネタ

球体描画(model sphere.lua)

ミラーボールの描画

もともとは球体を作るサンプルの一発ネタとしてミラーボールを描画してたのでそれなりに汎用性はあります。

事前準備:

使い方

  • 必要なのはmodel sphere.luaとmodel lid.lua、model ring.luaの3ファイルです。
    • あ、貼り付けるテクスチャとしてmirror.pngも必要です。
  • model sphereをLoadActorで呼び出します。
  • 第2引数は識別用IDです。数値でも文字列でも構いません。
  • 第3引数は大きさや解像度、テクスチャを設定します。
    • よく見るとTextureの指定が必須でした。全然汎用性ないですね。
LoadActor('model sphere', 'ID', {Texture = {File = GAMESTATE:GetCurrentSong():GetSongDir()..'mirror.png',Uv = {}}})

見づらいんでテーブルを改行します。

LoadActor('model sphere', 'ID', {
    Texture = {
        File = GAMESTATE:GetCurrentSong():GetSongDir()..'mirror.png',
        Uv = {},
    },
})

はい、見やすい。 これで次のような物体が表示されます。

ミラー…ボール…?

はい、球体表示といっても実際はmodel ring.luaで筒状の物体を上下の口の大きさを変えて縦に並べているだけなのできれいな円にしようとすればするほど処理が重くなります。

というわけで、デフォルトは解像度レベル8(4段階の角度が付く)設定になっています。使えないレベルの低解像度じゃん。

解像度の値を大きく設定することできれいな球体になります。 とはいえ、あまり大きくしたところでパッと見わからないので、そこまで大きくする必要はないと思います。

LoadActor('model sphere', 'ID', {
    Resolution = 20,    -- 解像度
    Texture = {
        File = GAMESTATE:GetCurrentSong():GetSongDir()..'mirror.png',
        Uv = {},
    },
})

はいキレイ!


次にテクスチャの設定。

パラメータのTexture['File']に画像ファイルパスを指定すればいいわけですが、どういうわけか相対パスを設定しても反映されないのでStepManiaのディレクトリからのパスになります。全然汎用性ないですね。

例えば楽曲内で使用する場合はGAMESTATE:GetCurrentSong():GetSongDir()..'mirror.png'
テーマ内で使用する場合はTHEME:GetPathG('', 'mirror.png')といった感じで指定してあげるといい感じになります。

なお、テクスチャ画像のサイズですが、縦・横いずれも2の累乗のサイズにすると綺麗に表示されます。
4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048
ただし、StepManiaのデフォルト設定では2048を超えると自動的に調整されるのでぼやけます。そんなデカい画像使うなって話ですけどね。

次に、UV座標の設定です。テクスチャのどの部分を使うかの設定ですね。

画像ファイルの左を0、右を1、上を0、下を1として、どの範囲を使うか左、上、右、下の順で設定します。
デフォルト({}だけ指定した場合)は{0, 0, 1, 1}となります。

LoadActor('model sphere', 'ID', {
    Resolution = 20,
    Texture = {
        File = GAMESTATE:GetCurrentSong():GetSongDir()..'mirror.png',
        Uv = {0.5, 0.8, 0.6, 1.0},    -- UV座標(左、上、右、下)
    },
})

※画像の黄色い枠の部分が使用される

あれ…Xの切り取りおかしいような…(バグです)

修正したんでこっちのmodel ringを使用してください。
https://github.com/waiei/note/tree/master/lua/sphere

はい、バッチリ。


スイカの描画

ここに画像を用意しているのでこれを使ってスイカを作ってみます。
https://github.com/waiei/note/blob/master/lua/sphere/suika.png

まずは普通に作成して斜め上からの視点で描画します。

LoadActor('model sphere', 'ID', {
    Resolution = 20,
    Texture = {
        File = GAMESTATE:GetCurrentSong():GetSongDir()..'suika.png',
        Uv = {0, 0, 1, 0.5},    -- 外側のテクスチャは縦半分なので下の値は0.5にする
    },
})..{
    InitCommand = cmd(rotationx,30),    -- 普通のLoadActor感覚でコマンドが書ける
}

はい、スイカですね。

せっかくなのでカットして中身が見えるようにしたいです。
パラメーターにSliceを設定することで高さを指定して球体をカットすることができます。
上を0、下を1として上下どこでカットするか設定します。

もちろん、{0, 1}の場合はカットしていない状態と同じです。

LoadActor('model sphere', 'ID', {
    Resolution = 20,
    Texture = {
        File = GAMESTATE:GetCurrentSong():GetSongDir()..'suika.png',
        Uv = {0, 0, 1, 0.5},
    },
    Slice = {0.3, 0.9},    -- 上から0.3~0.9の部分を残してカット
})..{
    InitCommand = cmd(rotationx,30),
}

ちょっとわかりにくいですが、中身は空洞になっていてぽっかりと穴が開いた感じになっています。 なので上下にテクスチャを貼って、中身が詰まっているように見せます。

テクスチャは、左上から右下の座標を設定すると、丸く切り取られて貼り付けられます。

つまり、上の画像の青い円の外側は無視されます。

LoadActor('model sphere', 'ID', {
    Resolution = 20,
    Texture = {
        File = GAMESTATE:GetCurrentSong():GetSongDir()..'suika.png',
        Uv = {0, 0, 1, 0.5},
        TopUv = {0, 0.5, 0.5, 1},    -- 上側のテクスチャ座標
        BottomUv = {0.5, 0.5, 1, 1},    -- 下側のテクスチャ座標
    },
    Slice = {0.3, 0.9},
})..{
    InitCommand = cmd(rotationx,30),
}

回転させてみると下側もテクスチャが貼られていることがわかります。

LoadActor('model sphere', 'ID', {
    Resolution = 20,
    Texture = {
        File = GAMESTATE:GetCurrentSong():GetSongDir()..'suika.png',
        Uv = {0, 0, 1, 0.5},
        TopUv = {0, 0.5, 0.5, 1},
        BottomUv = {0.5, 0.5, 1, 1},
    },
    Slice = {0.3, 0.9},
})..{
    InitCommand = cmd(spin;effectmagnitude,50,0,0),    -- 縦回転
}

残念ながら食べる時によく見る1/6カットみたいなことは出来ないです。
あくまで球体の範囲なので。

頑張れば某ゲームのマスコット的キャラクターも作ることができます!


Q&A

  • 半透明なテクスチャ画像を使うと前後関係がうまくいきません、ていうか透過処理されてません
    • 3Dの半透明処理ムズイねん…
    • zbuffer使ってる弊害なので良い感じに修正できたらプルリク送ってくれてもいいのよ。
Clone this wiki locally