Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- [ExecuteInEditMode]
- public class Liquid : MonoBehaviour
- {
- Vector3 velocity;
- Vector3 angularVelocity;
- Vector3 lastPos;
- Quaternion lastRot;
- Transform tr;
- public Mesh mesh;
- public Renderer rend;
- float wobbleAddX, wobbleAddZ = 0;
- public float wobbleMoveSpeed = 5f;
- public float recoverySpeed = 0.8f;
- float sinX;
- float sinewave;
- bool isMoving = false;
- [Range(0, 0.05f)]
- public float maxWobble = 0.025f;
- float time = 1f;
- float deltaTime = 0;
- Vector3 localYDirection;
- void Start()
- {
- tr = GetComponent<Transform>();
- lastPos = tr.position; //시작 가속도를 없애기 위해 설정
- if (mesh == null)
- {
- mesh = GetComponent<MeshFilter>().sharedMesh;
- }
- if (rend == null)
- {
- rend = GetComponent<Renderer>();
- }
- wobbleAddX = 0;
- wobbleAddZ = 0;
- }
- void Update()
- {
- deltaTime = Time.deltaTime;
- //움직이는동안에는 시간을 더해주는 것을 멈추어 물이 좌우로 움직이는 것을 멈춘다.
- if (!isMoving)
- { time += deltaTime; }
- //액체 움직임정도를 shader에 보낸다.
- VelocityCalculation(deltaTime);
- //Mesh의 가장 밑부분을 shader에 보낸다.
- rend.sharedMaterial.SetFloat("_WorldLowestYPos", GetLowestPoint());
- //local Y Direction을 shader에 보낸다.
- localYDirection = this.tr.up;
- rend.sharedMaterial.SetVector("_LocalYDir", localYDirection.normalized);
- //foam 위치
- Vector3 WSCenterPos = tr.TransformPoint(new Vector3(mesh.bounds.center.x, mesh.bounds.center.y, mesh.bounds.center.z));
- //float WSPosY = tr.position.y;
- rend.sharedMaterial.SetFloat("_WSPosY", WSCenterPos.y);
- }
- void VelocityCalculation(float deltaTime)
- {
- Vector3 currentPos = tr.position;
- Quaternion currentRot = tr.rotation;
- //sin y값에 의해 좌우로 흔들리게 된다. sin x좌표의 위치를 지정해두는 것 1.0f/2.0f 5/2는 y값이 1이 나오기 때문 나눠줄때는 float 값으로 나눠주어야 float 값결과가 제대로 나온다.
- sinX = 1.0f / 2.0f * Mathf.PI * wobbleMoveSpeed;
- //velocity.magnitude혹은angularVelocity.magnitude가 0보다 크면 sin x좌표의 움직임을 멈춘다.
- // if (velocity.magnitude > 0 || angularVelocity.magnitude > 0)
- // { isMoving = true; time = 1; }
- if (currentPos != lastPos || currentRot != lastRot)
- { isMoving = true; time = 1; }
- else
- { isMoving = false; }
- //sin y축 값
- sinewave = Mathf.Sin(sinX * time);
- wobbleAddX = Mathf.Lerp(wobbleAddX, 0, deltaTime * recoverySpeed);
- wobbleAddZ = Mathf.Lerp(wobbleAddZ, 0, deltaTime * recoverySpeed);
- //속력 구하기
- velocity = (lastPos - currentPos) / deltaTime;
- angularVelocity = GetAngularVelocity(lastRot, currentRot);
- //new Temp
- //angularVelocity = GetPedestrianAngularVelocity();
- //maxWobble 값을 꼭 설정할 것 //속력을 낼수록 액체의 각도를 점점 기울인다.
- wobbleAddX += Mathf.Clamp(velocity.x + velocity.y * 0.01f, -maxWobble, maxWobble);
- wobbleAddZ += Mathf.Clamp(velocity.z + velocity.y * 0.01f, -maxWobble, maxWobble);
- wobbleAddX += Mathf.Clamp(angularVelocity.z, -maxWobble - 0.03f, maxWobble + 0.03f);
- wobbleAddZ += Mathf.Clamp(angularVelocity.x, -maxWobble - 0.03f, maxWobble + 0.03f);
- float wobbleX = wobbleAddX * sinewave;
- float wobbleZ = wobbleAddZ * sinewave;
- lastPos = tr.position;
- lastRot = tr.rotation;
- rend.sharedMaterial.SetFloat("_WobbleX", wobbleX);
- rend.sharedMaterial.SetFloat("_WobbleZ", -wobbleZ);
- }
- //각 속도
- Vector3 GetAngularVelocity(Quaternion foreLastFrameRotation, Quaternion lastFrameRotation)
- {
- var q = lastFrameRotation * Quaternion.Inverse(foreLastFrameRotation);
- // no rotation?
- // You may want to increase this closer to 1 if you want to handle very small rotations.
- // Beware, if it is too close to one your answer will be Nan
- if (Mathf.Abs(q.w) > 1023.9f / 1024.0f) //if (Mathf.Abs(q.w) > 1023.5f / 1024.0f)
- return Vector3.zero;
- float gain;
- // handle negatives, we could just flip it but this is faster
- if (q.w < 0.0f)
- {
- var angle = Mathf.Acos(-q.w);
- gain = -2.0f * angle / (Mathf.Sin(angle) * Time.deltaTime);
- }
- else
- {
- var angle = Mathf.Acos(q.w);
- gain = 2.0f * angle / (Mathf.Sin(angle) * Time.deltaTime);
- }
- Vector3 angularVelocity = new Vector3(q.x * gain, q.y * gain, q.z * gain);
- if (float.IsNaN(angularVelocity.z))
- {
- angularVelocity = Vector3.zero;
- }
- return angularVelocity;
- }
- //가장 밑부분 vertex position 찾기
- float GetLowestPoint()
- {
- float lowestY = float.MaxValue;
- Vector3 lowestVert = Vector3.zero;
- Vector3[] vertices = mesh.vertices;
- for (int i = 0; i < vertices.Length; i++)
- {
- Vector3 position = transform.TransformPoint(vertices[i]);
- if (position.y < lowestY)
- {
- lowestY = position.y;
- lowestVert = position;
- }
- }
- return lowestVert.y;
- }
- //Angular Velocity
- Quaternion previousRotation; //전 프레임의 로테이션 값
- //Vector3 angularVelocity; //각속도를 관리할 변수
- //이 함수를 업데이트에서 굴려줍니다.
- public Vector3 GetPedestrianAngularVelocity()
- {
- Quaternion deltaRotation = tr.rotation * Quaternion.Inverse(previousRotation);
- previousRotation = tr.rotation;
- deltaRotation.ToAngleAxis(out var angle, out var axis);
- //각도에서 라디안으로 변환
- angle *= Mathf.Deg2Rad;
- angularVelocity = (1.0f / Time.deltaTime) * angle * axis;
- //각속도 반환
- return angularVelocity;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement