vci.studio(ExportStudio)&(ExportSystemItem)を使ってカメラを動かします。
Luaでモーションを制御してるので、下記のプログラミングを書き換える事でアングルをアレンジする事ができます。
下記スクリプトは変更したり、自由にコピー&ペーストしても問題ありません。
Targetは演者の人に装着してもらい、演者の位置を取得するのに使用します。
Targetの位置と向きを基準にカメラが自動で動きます。また、ターゲットの方向を注視します。
local _target = vci.assets.GetTransform("Target") local _motionType = 1 -- 現在再生中のモーション local _lastMotionType = 0 -- 前回再生したモーションを保存する local _motionIsActive = false -- trueならカメラの移動を実行 local _resetIsActive = false -- trueならカメラの位置をリセット -- カット切り替え時のターゲットの位置・回転を保存 local _fixTargetPosition local _fixTargetRotation -- LookAtの補正 local _LookAtoffset = 10.0 -- +の値でカメラは上方向を注視するようになります -- カメラの位置 local _camPosition -- Min ~ Max の範囲でランダムな値になります local _posxMax = 1.6 -- X軸(左右) local _posxMin = -1.6 local _posyMax = 1.5 -- Y軸(上下) local _posyMin = 0.5 local _poszMax = 2.0 -- Z軸(前後) local _poszMin = 0.8 -- カメラとターゲットの間隔 local _camDistance local _distanceMax = 3.5 -- 最長距離 local _distanceMin = 1.5 -- 最短距離 -- カメラが回転するのにかかる時間 local _camCycleTime local _cycleTimeMax = 30.0 local _cycleTimeMin = 10.0 ------------------------------------------------------------ -- カメラの位置をランダムで決定 function randomPosition() local x = 0.1 * math.random(10.0 * _posxMin, 10.0 * _posxMax) local y = 0.1 * math.random(10.0 * _posyMin, 10.0 * _posyMax) local z = 0.1 * math.random(10.0 * _poszMin, 10.0 * _poszMax) _camPosition = Vector3.__new(x, y, z) end -- カメラとターゲットの間隔をランダムで決定 function randomDistance() _camDistance = 0.1 * math.random(10.0 * _distanceMin, 10.0 * _distanceMax) end -- カメラが回転にかかる時間をランダムで決定 function randomSpeed() _camCycleTime = 0.1 * math.random(10.0 * _cycleTimeMin, 10.0 * _cycleTimeMax) end -- 次に使用するカメラのモーションをランダムで決定 function randomMotion() while _lastMotionType == _motionType do -- カメラモーションの数 _motionType = math.random(1, 4) end _lastMotionType = _motionType end -- 初期値の決定 randomDistance() -- _camDistance randomPosition() -- _camPosition randomSpeed() -- _camCycleTime _fixTargetPosition = _target.GetPosition() _fixTargetRotation = _target.GetRotation() function onUse(use) -- カメラのモーション切り替え if use == "Switcher" then randomMotion() randomDistance() randomPosition() randomSpeed() _fixTargetPosition = _target.GetPosition() _fixTargetRotation = _target.GetRotation() print("Motion Type : "..tostring(_motionType)) print("cam Position : "..tostring(_camPosition)) print("cam Distance : "..tostring(_camDistance)) print("cam Speed : "..tostring(_camCycleTime)) end -- 固定のカメラモーションに切り替え if use == "FixSwitcher" then _motionType = 3 _lastMotionType = _motionType _fixTargetPosition = _target.GetPosition() print("Motion Type : "..tostring(_motionType)) end -- カメラモーションの有効・無効 if use == "Power" then _motionIsActive = not(_motionIsActive) print("Active : "..tostring(_motionIsActive)) end -- カメラモーションを停止して位置をリセット if use == "Reset" then _motionIsActive = false _resetIsActive = true print("Active : "..tostring(_motionIsActive)) end end function onUnuse(use) -- カメラモーションを停止して位置をリセット if use == "Reset" then _resetIsActive = false end end function update() cameraMotion() resetPosition() end --カメラモーションの実行 function cameraMotion() -- カメラモーションが無効なので終了 if _motionIsActive == false then return end --ハンディカメラが存在しない場合終了 if vci.studio.HasHandiCamera() == false then -- print("ハンディカメラが存在しません") return end -- モーション割り振り if _motionType == 1 then motionType1() end if _motionType == 2 then motionType2() end if _motionType == 3 then motionType3() end if _motionType == 4 then motionType4() end end -- LookAt function LookAt() local cam = vci.studio.GetHandiCamera() local forward = _target.GetPosition() - cam.GetPosition() forward = forward.normalized local rot = Quaternion.LookRotation(forward, Vector3.up) rot = rot * Quaternion.AngleAxis(_LookAtoffset, Vector3.left) --向き補正 cam.SetRotation(rot) end -- LookAt(Fix) function LookAtFix() local cam = vci.studio.GetHandiCamera() local forward = _fixTargetPosition - cam.GetPosition() forward = forward.normalized local rot = Quaternion.LookRotation(forward, Vector3.up) rot = rot * Quaternion.AngleAxis(_LookAtoffset, Vector3.left) --向き補正 cam.SetRotation(rot) end -- LookAt(Lerp) function LookAtLerp() local cam = vci.studio.GetHandiCamera() local forward = _target.GetPosition() - cam.GetPosition() forward = forward.normalized local target = Quaternion.LookRotation(forward, Vector3.up) target = target * Quaternion.AngleAxis(_LookAtoffset, Vector3.left) --向き補正 local rot = Quaternion.Lerp(cam.GetRotation(), target, 0.016) cam.SetRotation(rot) end -- ターゲットの周りを回転しながら、ターゲットの方向を向く function motionType1() local cam = vci.studio.GetHandiCamera() -- 回転処理 local cycleTime = _camCycleTime --cycleTimeを増やすと1周にかかる時間が増えます local f = 1.0 / cycleTime local time = 6.283185 * f * os.time() local sin = math.sin(time) local cos = math.cos(time) -- 位置 & offset local y = _camPosition.y -- カメラの高さ local x = sin * _camDistance + _fixTargetPosition.x local z = cos * _camDistance + _fixTargetPosition.z local pos = Vector3.__new(x, y, z) -- SetPosition cam.SetPosition(pos) -- LookAt LookAtFix() end -- ターゲットの位置を基準にランダムな位置へカメラを移動し、ターゲットの方向を向く -- スイッチングカメラと似た挙動ですが、デフォルト設定だと正面方向のみから位置が選出されます function motionType2() local cam = vci.studio.GetHandiCamera() -- 位置 local pos = _fixTargetRotation * _camPosition -- offset pos = pos + _fixTargetPosition -- SetPosition cam.SetPosition(pos) -- LookAt LookAtFix() end -- 正面方向からバストアップ function motionType3() local cam = vci.studio.GetHandiCamera() -- 位置 local distance = 0.8 --ターゲットとカメラの間隔 local height = 0.2 --カメラの高さ local pos = _target.GetRotation() * Vector3.__new(0, height, 1.0) * distance -- offset pos = pos + _target.GetPosition() -- SetPosition cam.SetPosition(pos) -- LookAt LookAtLerp() end -- 斜め正面方向からバストアップ function motionType4() local cam = vci.studio.GetHandiCamera() -- 位置 local distance = 0.7 --ターゲットとカメラの間隔 local height = 0.2 --カメラの高さ local pos = _target.GetRotation() * Vector3.__new(0, height, 1.0) * distance pos = Quaternion.AngleAxis(45, Vector3.up) * pos pos = Vector3.Lerp(pos, cam.GetPosition(), 0.02) -- offset pos = pos + _target.GetPosition() -- SetPosition cam.SetPosition(pos) -- LookAt LookAtLerp() end -- 位置をリセット function resetPosition() -- リセット中でなければ終了 if _resetIsActive == false then return end local cam = vci.studio.GetHandiCamera() -- 位置 local front = _target.GetRotation() * Vector3.__new(0, 0, 0.5) front = front + _target.GetPosition() cam.SetPosition(front) cam.SetRotation(Quaternion.identity) end
こちらの値を+にするとターゲットより上の方向にカメラが向き、-の値にするとターゲットより下を向きます。
値を0にする事で、ターゲットの方向に向くようになります。
スイッチング時にランダムで位置を決定しているので、MinとMaxの値を変える事でランダムの範囲を制御できます。
_poszMinにマイナスの値を入れると背後から撮るアングルも選択されるようになります。
ターゲットを中心にして回転するアングルを選択した時の距離。
Maxの値を大きくとると、ターゲットから離れたアングルを選択するようになります。
カメラの回転速度になります。回転速度を上げたい場合はMinとMaxの両方の値を上げます。
_camCycleTimeが定数になるように書き換えれば回転速度は一定になります。
実行するとカメラがターゲットの方向を向きます。
LookAt()は補間なしでターゲットの方向を向き、LookAtFix()はスイッチングした直後の向きで固定します。
LookAtLerp()は補間ありで、なめらかにターゲットの方向を向きます。
local num = math.random(1, 10)
Luaのランダムは第一引数から第二引数の値で整数の値を返します。
なので上の場合、numは1,2,3…10という値になります。
しかし、ランダムで位置を決めるような場合、上記の書き方では1m毎になってしまうのであまり好ましくありません。
なので下記のような書き方をします。
local Min = 1 local Max = 10 local num = 0.1 * math.random(10.0 * Min, 10.0 * Max)
MinとMaxを10倍してから、結果を0.1倍すると、0.1刻みのランダムを得る事ができます。
同様に 100倍して結果を0.01倍すると、0.01刻みのランダムになります。
用途によってランダムの調整をする事ができます。