/** * 更新 * 首を中央から左右に振るときの平均的な早さは 秒程度。加速・減速を考慮して、その2倍を最高速度とする * 顔のふり具合を、中央(0)から、左右は(±1)とする */ public void update() { // const float TIME_TO_MAX_SPEED = 0.15f; //最高速度になるまでの時間 const float FACE_PARAM_MAX_V = 40.0f / 7.5f; //7.5秒間に40分移動(5.3/sc) const float MAX_V = FACE_PARAM_MAX_V / FRAME_RATE; //1frameあたりに変化できる速度の上限 if (lastTimeSec == 0) { lastTimeSec = UtSystem.getUserTimeMSec(); return; } long curTimeSec = UtSystem.getUserTimeMSec(); float deltaTimeWeight = (float)(curTimeSec - lastTimeSec) * FRAME_RATE / 1000.0f; lastTimeSec = curTimeSec; const float FRAME_TO_MAX_SPEED = TIME_TO_MAX_SPEED * FRAME_RATE; //sec*frame/sec float MAX_A = deltaTimeWeight * MAX_V / FRAME_TO_MAX_SPEED; //1frameあたりの加速度 float dx = (faceTargetX - faceX); float dy = (faceTargetY - faceY); if (dx == 0 && dy == 0) { return; } float d = (float)Math.Sqrt(dx * dx + dy * dy); float vx = MAX_V * dx / d; float vy = MAX_V * dy / d; float ax = vx - faceVX; float ay = vy - faceVY; float a = (float)Math.Sqrt(ax * ax + ay * ay); if (a < -MAX_A || a > MAX_A) { ax *= MAX_A / a; ay *= MAX_A / a; a = MAX_A; } faceVX += ax; faceVY += ay; { // 2 6 2 3 // sqrt(a t + 16 a h t - 8 a h) - a t // v = -------------------------------------- // 2 // 4 t - 2 //(t=1) float max_v = 0.5f * ((float)Math.Sqrt(MAX_A * MAX_A + 16 * MAX_A * d - 8 * MAX_A * d) - MAX_A); float cur_v = (float)Math.Sqrt(faceVX * faceVX + faceVY * faceVY); if (cur_v > max_v) { faceVX *= max_v / cur_v; faceVY *= max_v / cur_v; } } faceX += faceVX; faceY += faceVY; }
/* * モデルのパラメータを更新。 * @param model */ public void updateParam(ALive2DModel model) { long time = UtSystem.getUserTimeMSec(); float eyeParamValue;// 設定する値 float t = 0; switch (this.eyeState) { case EYE_STATE.STATE_CLOSING: // 閉じるまでの割合を0..1に直す(blinkMotionMsecの半分の時間で閉じる) t = (time - stateStartTime) / (float)closingMotionMsec; if (t >= 1) { t = 1; this.eyeState = EYE_STATE.STATE_CLOSED;// 次から開き始める this.stateStartTime = time; } eyeParamValue = 1 - t; break; case EYE_STATE.STATE_CLOSED: t = (time - stateStartTime) / (float)closedMotionMsec; if (t >= 1) { this.eyeState = EYE_STATE.STATE_OPENING;// 次から開き始める this.stateStartTime = time; } eyeParamValue = 0; // 閉じた状態 break; case EYE_STATE.STATE_OPENING: t = (time - stateStartTime) / (float)openingMotionMsec; if (t >= 1) { t = 1; this.eyeState = EYE_STATE.STATE_INTERVAL; // 次から開き始める this.nextBlinkTime = calcNextBlink(); // 次回のまばたきのタイミングを始める時刻 } eyeParamValue = t; break; case EYE_STATE.STATE_INTERVAL: // if (this.nextBlinkTime < time) { this.eyeState = EYE_STATE.STATE_CLOSING; this.stateStartTime = time; } eyeParamValue = 1; // 開いた状態 break; case EYE_STATE.STATE_FIRST: default: this.eyeState = EYE_STATE.STATE_INTERVAL; this.nextBlinkTime = calcNextBlink(); // 次回のまばたきのタイミングを始める時刻 eyeParamValue = 1; // 開いた状態 break; } if (!closeIfZero) { eyeParamValue = -eyeParamValue; } // ---- 値を設定 ---- model.setParamFloat(eyeID_L, eyeParamValue); model.setParamFloat(eyeID_R, eyeParamValue); }
/* * 更新 */ public void Update() { if (!isInitialized() || isUpdating()) { return; } view.Update(Input.acceleration); if (live2DModel == null) { if (LAppDefine.DEBUG_LOG) { Debug.Log("Can not update there is no model data"); } return; } if (!Application.isPlaying) { live2DModel.update(); return; } long timeMSec = UtSystem.getUserTimeMSec() - startTimeMSec; double timeSec = timeMSec / 1000.0; double t = timeSec * 2 * Math.PI;// 2πt // 待機モーション判定 if (mainMotionManager.isFinished()) { // モーションの再生がない場合、待機モーションの中からランダムで再生する StartRandomMotion(LAppDefine.MOTION_GROUP_IDLE, LAppDefine.PRIORITY_IDLE); } //----------------------------------------------------------------- live2DModel.loadParam(); // 前回セーブされた状態をロード bool update = mainMotionManager.updateParam(live2DModel); // モーションを更新 if (!update) { // メインモーションの更新がないとき eyeBlink.updateParam(live2DModel);// 目パチ } live2DModel.saveParam();// 状態を保存 //----------------------------------------------------------------- if (expressionManager != null) { expressionManager.updateParam(live2DModel); // 表情でパラメータ更新(相対変化) } // ドラッグによる変化 // ドラッグによる顔の向きの調整 live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_X, dragX * 30, 1);// -30から30の値を加える live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_Y, dragY * 30, 1); live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_Z, (dragX * dragY) * -30, 1); // ドラッグによる体の向きの調整 live2DModel.addToParamFloat(L2DStandardID.PARAM_BODY_ANGLE_X, dragX, 10);// -10から10の値を加える // ドラッグによる目の向きの調整 live2DModel.addToParamFloat(L2DStandardID.PARAM_EYE_BALL_X, dragX, 1);// -1から1の値を加える live2DModel.addToParamFloat(L2DStandardID.PARAM_EYE_BALL_Y, dragY, 1); // 呼吸など live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_X, (float)(15 * Math.Sin(t / 6.5345)), 0.5f); live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_Y, (float)(8 * Math.Sin(t / 3.5345)), 0.5f); live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_Z, (float)(10 * Math.Sin(t / 5.5345)), 0.5f); live2DModel.addToParamFloat(L2DStandardID.PARAM_BODY_ANGLE_X, (float)(4 * Math.Sin(t / 15.5345)), 0.5f); live2DModel.setParamFloat(L2DStandardID.PARAM_BREATH, (float)(0.5f + 0.5f * Math.Sin(t / 3.2345)), 1); // 加速度による変化 live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_X, 90 * accelX, 0.5f); live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_Z, 10 * accelX, 0.5f); if (physics != null) { physics.updateParam(live2DModel); // 物理演算でパラメータ更新 } // リップシンクの設定 if (lipSync) { live2DModel.setParamFloat(L2DStandardID.PARAM_MOUTH_OPEN_Y, lipSyncValue, 0.8f); } // ポーズの設定 if (pose != null) { pose.updateParam(live2DModel); } live2DModel.update(); }
public void Update() { if (!isInitialized() || isUpdating()) { return; } view.Update(Input.acceleration); if (live2DModel == null) { if (LAppDefine.DEBUG_LOG) { Debug.Log("Can not update there is no model data"); } return; } if (!Application.isPlaying) { live2DModel.update(); return; } long timeMSec = UtSystem.getUserTimeMSec() - startTimeMSec; double timeSec = timeMSec / 1000.0; double t = timeSec * 2 * Math.PI; if (mainMotionManager.isFinished()) { StartRandomMotion(LAppDefine.MOTION_GROUP_IDLE, LAppDefine.PRIORITY_IDLE); } //----------------------------------------------------------------- live2DModel.loadParam(); bool update = mainMotionManager.updateParam(live2DModel); if (!update) { eyeBlink.updateParam(live2DModel); } live2DModel.saveParam(); //----------------------------------------------------------------- if (expressionManager != null) { expressionManager.updateParam(live2DModel); } live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_X, dragX * 30, 1); live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_Y, dragY * 30, 1); live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_Z, (dragX * dragY) * -30, 1); live2DModel.addToParamFloat(L2DStandardID.PARAM_BODY_ANGLE_X, dragX, 10); live2DModel.addToParamFloat(L2DStandardID.PARAM_EYE_BALL_X, dragX, 1); live2DModel.addToParamFloat(L2DStandardID.PARAM_EYE_BALL_Y, dragY, 1); live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_X, (float)(15 * Math.Sin(t / 6.5345)), 0.5f); live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_Y, (float)(8 * Math.Sin(t / 3.5345)), 0.5f); live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_Z, (float)(10 * Math.Sin(t / 5.5345)), 0.5f); live2DModel.addToParamFloat(L2DStandardID.PARAM_BODY_ANGLE_X, (float)(4 * Math.Sin(t / 15.5345)), 0.5f); live2DModel.setParamFloat(L2DStandardID.PARAM_BREATH, (float)(0.5f + 0.5f * Math.Sin(t / 3.2345)), 1); live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_X, 90 * accelX, 0.5f); live2DModel.addToParamFloat(L2DStandardID.PARAM_ANGLE_Z, 10 * accelX, 0.5f); if (physics != null) { physics.updateParam(live2DModel); } if (lipSync) { live2DModel.setParamFloat(L2DStandardID.PARAM_MOUTH_OPEN_Y, lipSyncValue, 0.8f); } if (pose != null) { pose.updateParam(live2DModel); } if (thalmicMyo.pose == Pose.Rest) { SetExpression("f01"); } else if (thalmicMyo.pose == Pose.WaveIn) { SetExpression("f02"); } else if (thalmicMyo.pose == Pose.Fist) { SetExpression("f03"); } else if (thalmicMyo.pose == Pose.FingersSpread) { SetExpression("f04"); } if (thalmicMyo.pose == Pose.DoubleTap) { acVoice = FileManager.LoadAssetsSound(modelHomeDir + "sounds/pinchOut_02"); StartVoice(acVoice); } live2DModel.update(); }
/** * コンストラクタ */ public L2DPhysics() { physicsList = new List <PhysicsHair>(); startTimeMSec = UtSystem.getUserTimeMSec(); }
public void updateParam(ALive2DModel model) { long time = UtSystem.getUserTimeMSec(); float eyeParamValue; float t = 0; switch (this.eyeState) { case EYE_STATE.STATE_CLOSING: t = (time - stateStartTime) / (float)closingMotionMsec; if (t >= 1) { t = 1; this.eyeState = EYE_STATE.STATE_CLOSED; this.stateStartTime = time; } eyeParamValue = 1 - t; break; case EYE_STATE.STATE_CLOSED: t = (time - stateStartTime) / (float)closedMotionMsec; if (t >= 1) { this.eyeState = EYE_STATE.STATE_OPENING; this.stateStartTime = time; } eyeParamValue = 0; break; case EYE_STATE.STATE_OPENING: t = (time - stateStartTime) / (float)openingMotionMsec; if (t >= 1) { t = 1; this.eyeState = EYE_STATE.STATE_INTERVAL; this.nextBlinkTime = calcNextBlink(); } eyeParamValue = t; break; case EYE_STATE.STATE_INTERVAL: // if (this.nextBlinkTime < time) { this.eyeState = EYE_STATE.STATE_CLOSING; this.stateStartTime = time; } eyeParamValue = 1; break; case EYE_STATE.STATE_FIRST: default: this.eyeState = EYE_STATE.STATE_INTERVAL; this.nextBlinkTime = calcNextBlink(); eyeParamValue = 1; break; } if (!closeIfZero) { eyeParamValue = -eyeParamValue; } model.setParamFloat(eyeID_L, eyeParamValue); model.setParamFloat(eyeID_R, eyeParamValue); }