123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- /**
- * Copyright(c) Live2D Inc. All rights reserved.
- *
- * Use of this source code is governed by the Live2D Open Software license
- * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
- */
- using Live2D.Cubism.Core;
- using System;
- using UnityEngine;
- namespace Live2D.Cubism.Framework.Physics
- {
- /// <summary>
- /// Children of rig.
- /// </summary>
- [Serializable]
- public class CubismPhysicsSubRig
- {
- /// <summary>
- /// Input.
- /// </summary>
- [SerializeField]
- public CubismPhysicsInput[] Input;
- /// <summary>
- /// Output.
- /// </summary>
- [SerializeField]
- public CubismPhysicsOutput[] Output;
- /// <summary>
- /// Particles.
- /// </summary>
- [SerializeField]
- public CubismPhysicsParticle[] Particles;
- /// <summary>
- /// Normalization.
- /// </summary>
- [SerializeField]
- public CubismPhysicsNormalization Normalization;
- /// <summary>
- /// Rig.
- /// </summary>
- public CubismPhysicsRig Rig
- {
- get { return _rig; }
- set { _rig = value; }
- }
- [NonSerialized]
- private CubismPhysicsRig _rig;
- /// <summary>
- /// Updates parameter from output value.
- /// </summary>
- /// <param name="parameter">Target parameter.</param>
- /// <param name="translation">Translation.</param>
- /// <param name="output">Output value.</param>
- private void UpdateOutputParameterValue(CubismParameter parameter, float translation, CubismPhysicsOutput output)
- {
- var outputScale = 1.0f;
- outputScale = output.GetScale();
- var value = translation * outputScale;
- if (value < parameter.MinimumValue)
- {
- if (value < output.ValueBelowMinimum)
- {
- output.ValueBelowMinimum = value;
- }
- value = parameter.MinimumValue;
- }
- else if (value > parameter.MaximumValue)
- {
- if (value > output.ValueExceededMaximum)
- {
- output.ValueExceededMaximum = value;
- }
- value = parameter.MaximumValue;
- }
- var weight = (output.Weight / CubismPhysics.MaximumWeight);
- if (weight >= 1.0f)
- {
- parameter.Value = value;
- }
- else
- {
- value = (parameter.Value * (1.0f - weight)) + (value * weight);
- parameter.Value = value;
- }
- }
- /// <summary>
- /// Updates particles in every frame.
- /// </summary>
- /// <param name="strand">Particles.</param>
- /// <param name="totalTranslation">Total translation.</param>
- /// <param name="totalAngle">Total angle.</param>
- /// <param name="wind">Direction of wind.</param>
- /// <param name="thresholdValue">Value of threshold.</param>
- /// <param name="deltaTime">Time of delta.</param>
- private void UpdateParticles(
- CubismPhysicsParticle[] strand,
- Vector2 totalTranslation,
- float totalAngle,
- Vector2 wind,
- float thresholdValue,
- float deltaTime
- )
- {
- strand[0].Position = totalTranslation;
- var totalRadian = CubismPhysicsMath.DegreesToRadian(totalAngle);
- var currentGravity = CubismPhysicsMath.RadianToDirection(totalRadian);
- currentGravity.Normalize();
- for (var i = 1; i < strand.Length; ++i)
- {
- strand[i].Force = (currentGravity * strand[i].Acceleration) + wind;
- strand[i].LastPosition = strand[i].Position;
- // The Cubism Editor expects 30 FPS so we scale here by 30...
- var delay = strand[i].Delay * deltaTime * 30.0f;
- var direction = strand[i].Position - strand[i - 1].Position;
- var radian = CubismPhysicsMath.DirectionToRadian(strand[i].LastGravity, currentGravity) / CubismPhysics.AirResistance;
- direction.x = ((Mathf.Cos(radian) * direction.x) - (direction.y * Mathf.Sin(radian)));
- direction.y = ((Mathf.Sin(radian) * direction.x) + (direction.y * Mathf.Cos(radian)));
- strand[i].Position = strand[i - 1].Position + direction;
- var velocity = strand[i].Velocity * delay;
- var force = strand[i].Force * delay * delay;
- strand[i].Position = strand[i].Position + velocity + force;
- var newDirection = strand[i].Position - strand[i - 1].Position;
- newDirection.Normalize();
- strand[i].Position = strand[i - 1].Position + newDirection * strand[i].Radius;
- if (Mathf.Abs(strand[i].Position.x) < thresholdValue)
- {
- strand[i].Position.x = 0.0f;
- }
- if (delay != 0.0f)
- {
- strand[i].Velocity =
- ((strand[i].Position - strand[i].LastPosition) / delay) * strand[i].Mobility;
- }
- strand[i].Force = Vector2.zero;
- strand[i].LastGravity = currentGravity;
- }
- }
- /// <summary>
- /// Initializes <see langword="this"/>.
- /// </summary>
- public void Initialize()
- {
- var strand = Particles;
- // Initialize the top of particle.
- strand[0].InitialPosition = Vector2.zero;
- strand[0].LastPosition = strand[0].InitialPosition;
- strand[0].LastGravity = Rig.Gravity;
- strand[0].LastGravity.y *= -1.0f;
- // Initialize particles.
- for (var i = 1; i < strand.Length; ++i)
- {
- var radius = Vector2.zero;
- radius.y = strand[i].Radius;
- strand[i].InitialPosition = strand[i - 1].InitialPosition + radius;
- strand[i].Position = strand[i].InitialPosition;
- strand[i].LastPosition = strand[i].InitialPosition;
- strand[i].LastGravity = Rig.Gravity;
- strand[i].LastGravity.y *= -1.0f;
- }
- // Initialize inputs.
- for (var i = 0; i < Input.Length; ++i)
- {
- Input[i].InitializeGetter();
- }
- // Initialize outputs.
- for (var i = 0; i < Output.Length; ++i)
- {
- Output[i].InitializeGetter();
- }
- }
- /// <summary>
- /// Evaluate rig in every frame.
- /// </summary>
- /// <param name="deltaTime"></param>
- public void Evaluate(float deltaTime)
- {
- var totalAngle = 0.0f;
- var totalTranslation = Vector2.zero;
- for (var i = 0; i < Input.Length; ++i)
- {
- var weight = Input[i].Weight / CubismPhysics.MaximumWeight;
- if (Input[i].Source == null)
- {
- Input[i].Source = Rig.Controller.Parameters.FindById(Input[i].SourceId);
- }
- var parameter = Input[i].Source;
- Input[i].GetNormalizedParameterValue(
- ref totalTranslation,
- ref totalAngle,
- parameter,
- Normalization,
- weight
- );
- }
- var radAngle = CubismPhysicsMath.DegreesToRadian(-totalAngle);
- totalTranslation.x = (totalTranslation.x * Mathf.Cos(radAngle) - totalTranslation.y * Mathf.Sin(radAngle));
- totalTranslation.y = (totalTranslation.x * Mathf.Sin(radAngle) + totalTranslation.y * Mathf.Cos(radAngle));
- UpdateParticles(
- Particles,
- totalTranslation,
- totalAngle,
- Rig.Wind,
- CubismPhysics.MovementThreshold * Normalization.Position.Maximum,
- deltaTime
- );
- for (var i = 0; i < Output.Length; ++i)
- {
- var particleIndex = Output[i].ParticleIndex;
- if (particleIndex < 1 || particleIndex >= Particles.Length)
- {
- break;
- }
- if (Output[i].Destination == null)
- {
- Output[i].Destination = Rig.Controller.Parameters.FindById(Output[i].DestinationId);
- }
- var parameter = Output[i].Destination;
- var translation = Particles[particleIndex].Position -
- Particles[particleIndex - 1].Position;
- var outputValue = Output[i].GetValue(
- translation,
- parameter,
- Particles,
- particleIndex,
- Rig.Gravity
- );
- UpdateOutputParameterValue(parameter, outputValue, Output[i]);
- }
- }
- }
- }
|