====== VCIでライブのようなカメラの動きを作る ======
[[https://developer.virtualcast.jp/vci-docs/api/classes/ExportStudio/index.html|vci.studio(ExportStudio)&(ExportSystemItem)]]を使ってカメラを動かします。\\
Luaでモーションを制御してるので、下記のプログラミングを書き換える事でアングルをアレンジする事ができます。\\
**下記スクリプトは変更したり、自由にコピー&ペーストしても問題ありません。**
=== サンプルデータ ===
https://virtualcast.jp/products/d386a9ccd752e956c4408bcef1c9098d6f81437404b088df53b57e2b6d88f81d
===== コンポーネント設定 =====
{{:vci:sample:systemitem:autolivecameravci.png?direct&700|}}
* PowerとResetはGrabできるだけのVCIです。スイッチとして使います。
* SwitcherとFixSwitcherとTargetは標準的な装着VCIです。
Targetは演者の人に装着してもらい、演者の位置を取得するのに使用します。\\
Targetの位置と向きを基準にカメラが自動で動きます。また、ターゲットの方向を注視します。
===== VCIスクリプト =====
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
===== 使い方(スクリプトの調整方法) =====
==== _LookAtoffset ====
こちらの値を+にするとターゲットより上の方向にカメラが向き、-の値にするとターゲットより下を向きます。\\
値を0にする事で、ターゲットの方向に向くようになります。
==== _camPosition ====
スイッチング時にランダムで位置を決定しているので、MinとMaxの値を変える事でランダムの範囲を制御できます。\\
_poszMinにマイナスの値を入れると背後から撮るアングルも選択されるようになります。
==== _camDistance ====
ターゲットを中心にして回転するアングルを選択した時の距離。\\
Maxの値を大きくとると、ターゲットから離れたアングルを選択するようになります。
==== _camCycleTime ====
カメラの回転速度になります。回転速度を上げたい場合はMinとMaxの両方の値を上げます。\\
_camCycleTimeが定数になるように書き換えれば回転速度は一定になります。
==== LookAt() ====
実行するとカメラがターゲットの方向を向きます。\\
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刻みのランダムになります。\\
用途によってランダムの調整をする事ができます。