OptifineのCEM Animationを学んでみる。
マイクラに登場する動物たちの外見を自分好みに変更する為にテクスチャの変更方法に加えてモデルのいじり方も学んできたわけですが、Optifineにはまだ機能があります。
アニメーションを変化する機能、CEM Animationです。他の方が作ったリソースパックにFresh Animationsというマイクラのモブたちに驚異的な動きをさせるものがありまして、それに触発されました。
Fresh Animations
https://www.curseforge.com/minecraft/texture-packs/fresh-animations
その紹介動画
自作のリソパ「Renewed Animal」もこんな風に動いたらすごそう!という訳で、Optifineの説明テキストを翻訳してみるところから始めてみます。
どうかなー。分かるかなー。
######################################################################
# カスタムエンティティモデルアニメーション
# Optifineのカスタムエンティティモデルのファイル参照機能のカスタマイズ方法
######################################################################
# アニメーションさせるための各モデルの動き(variable)には、特定の式が割り当てられます。
# その式はモデルがレンダリングされるたびに動きに割り当てられます。
# 変数と式は、Jsonエンティティモデル(JEM)の"animations"セクションで定義されます。
基本の形
"animations":
[
{
"動き1": "記述1",
"動き2": "記述2,
...
}
]
# 動き
# モデルの動きは次の形式で指定します
"<model>.<variable_name>"
# model は以下の形式をとることが出来ます:
# "this" - 現在のカスタムモデル
# "part" - カスタムモデルが追加されている、オリジナルのモデルパーツ
# "<part>" - オリジナルのモデルの中のパーツの名前
# "<id>" - カスタムモデルのID
# "<part>:<sub_id>:<sub_sub_id>:..." - (階層的) オリジナルのパーツ名からそれに付随するものへと辿ります
# "<id>:<sub_id>:<sub_sub_id>:..." - (階層的)オリジナルのIDからそれに付随するものへと辿ります
注
# 記述が重複する場合、早く記述されているモデルが使用されます。
# IDによるモデル検索は、階層を指定する場合でも深くなります。(?)
# 階層で指定することで、jsonパーツのモデルグループを様々なパーツで再利用できます。
# 例えば片手のモデル ("shoulder:upper_arm:elbow:forearm:palm:finger[1.5]" は左右両方に使用できます。
# この場合、アニメーションでは 左の親指に"left_hand:finger1" 、右の親指に"right_hand:finger1" と指定します。
# また、階層指定で途中に位置するものはスキップすることが出来ます。
# 動きの名前の短縮形
# tx, ty, tz - translation x, y, z (訳注:直線移動?)
# rx, ry, rz - rotation x, y, z (訳注:回転運動?)
# sx, sy, sz - scale x, y, z (訳注:大きさ変更?)
記述
# 記述は<>、定数、変数、演算子、関数を使用した一般的なものです。
# 定数 Constants として使用できるもの
# 不動小数点数 floating point number
# pi - 3.1415926
# true
# false
# 変数 Variables として使用できるもの
# <model>.<var> - モデル変数。モデル変数の仕様を参照して下さい。
# time - ティック単位でのワールド内の時間
# レンダリングパラメータ
# limb_swing - 手足のアニメーションカウンター(動かす回数?)
# limb_speed - 手足のアニメーションの速度
# age - ティック単位での年齢(?)
# head_yaw - 頭部の横振り運動
# head_pitch - 頭部の傾け
# エンティティパラメータ (float型 値で指定?)
# health (ヘルスの状態を指定)
# hurt_time (ダメージを受ける時間)
# idle_time (何もしない時間?)
# max_health (最大ヘルスの状態)
# move_forward (前に歩く)
# move_strafing (低空飛行で掃射する…?或いは非難する…どゆこと?)
# pos_x, pos_y, pos_z
# revenge_time (反撃する時間)
# swing_progress (振る 進捗 ?)
# エンティティパラメータ (boolean型 true false で指定?)特定の条件下でのアニメーションを作成できる?
# is_alive (生きている場合)
# is_burning (燃えている場合)
# is_child (子どもの場合)
# is_glowing (光っている場合?)
# is_hurt (ダメージを受けている場合)
# is_in_hand (装備されている場合?)
# is_in_ground (地中にいる場合)
# is_in_gui (メニュー内で表示されている場合?)
# is_in_lava (マグマの中にいる場合)
# is_in_water (水中にいる場合)
# is_invisible (透明な場合)
# is_on_ground (地上にいる場合)
# is_ridden (騎乗している場合?)
# is_riding (騎乗している場合?)
# is_sneaking (スニーク中の場合)
# is_sprinting (走っている場合)
# is_wet (濡れている場合)
# 演算子 Operators として使えるもの
# +, -, *, /, %
# !, &&, ||
# >, >=, <, <=, ==, !=
# 関数 Functions として使用できるもの
# sin(x) 短い範囲での運動を繰り返す
# cos(x) 短い範囲での運動を繰り返す(sinと同じ?)
# asin(x) 短い範囲での運動を繰り返す(sinの倍の速さ?)
# acos(x) 短い範囲での運動を繰り返す(asinと同じ?)
# tan(x) 反復運動ではなく、一方向への短い範囲での動きを繰り返す
# atan(x) 分からず
# atan2(y, x)
# torad(deg) 運動の角度?軸の向きを変える
# todeg(rad)
# min(x, y ,...)
# max(x, y, ...)
# clamp(x, min, max) 最大値と最小値を指定し、その範囲の値だけが有効になります
# abs(x) 円運動
# floor(x) absと同じ?
# ceil(x) absと同じ?
# exp(x) 良く分からない。鼻消えた
# frac(x) 超小刻みな振動
# log(x) 90度下を向いたまま
# pow(x) テクスチャ壊れ
# random(x) テクスチャ壊れ
# round(x) 円運動
# signum(x) 動かない?軸が向いてる向きが変わる?
# sqrt(x) 分からず。鼻消えた
# fmod(x, y) Math.floorMod()に近いです(?)
# if(cond, val, [cond2, val2, ...], val_else) 複数の条件に基づいて値を選択します。
# ブール関数 Boolean functions (True False のどちらかでのみ指定できる)
# between(x, min, max) 値が最小値と最大値の間にあるかどうかをチェックします
# equals(x, y, epsilon) 二つのフロート値をエラーマージンと比較します(?)
# in(x, val1, val2, ...) 値が指定されたいずれかのものと等しいかどうかをチェックします
以上を踏まえた記述例
# ...
# "animations":
# [
# {
# "this.rx": "clamp(-0.5 * part.rx, 0, 90)", このパーツのx軸の回転は-0.5単位で0~90の範囲で動く
# "this.tx": "3 * sin(limb_swing / 4) - 2", やっべ全然分からん…手足の振り方なんだろうけど
# "this:Hoof.rx": "if(leg4:Hoof.rx > 90, leg4:Hoof.rx - 90, 0)" 足4の蹄パーツが指定された場書にある場合?か?
# ...
# }
# ]
#
馬に蹄で地面を掻くようなアニメーションをさせるって記述かなぁ…?全然違ったりして。
ちょっと難しすぎるな…さすがにプログラムの勉強が要りそう。
ちょっとFresh Animationsの中身を見せてもらおう。参考になればいいけど…。