Created
November 11, 2021 10:51
-
-
Save varlamov5264/e07dc0cb8fd3cb1d0c626aca7aefa688 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
[RequireComponent(typeof(SkinnedMeshRenderer))] | |
public class FishingPole : MonoBehaviour | |
{ | |
// FishingPole is Singleton | |
private static FishingPole _instance; | |
public static FishingPole Instance | |
{ | |
get | |
{ | |
return _instance; | |
} | |
} | |
public Vector3 PoleTipPosition | |
{ | |
get | |
{ | |
return tip.position; | |
} | |
} | |
public float length | |
{ | |
get | |
{ | |
return (bones[0].position - tip.position).magnitude; | |
} | |
} | |
List<Transform> bones = new List<Transform>(); | |
public float m_forceModule = 0; | |
private Transform lastBone; | |
public Vector3 m_forceSource; | |
[SerializeField] | |
public int m_steps = 20; | |
public Material material; | |
public Space space; | |
private int segments = 5; | |
private Transform tip; | |
private void Awake() | |
{ | |
if (_instance != null) | |
{ | |
Destroy(this); | |
return; | |
} | |
_instance = this; | |
if (GetComponent<SkinnedMeshRenderer>().sharedMesh != null) | |
GetComponent<SkinnedMeshRenderer>().sharedMesh.Clear(); | |
GenerateMesh(); | |
this.gameObject.SetActive(false); | |
} | |
public void GenerateMesh() | |
{ | |
Transform transform = this.transform; | |
Matrix4x4 toLocal = transform.worldToLocalMatrix; | |
SkinnedMeshRenderer skinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>(); | |
List<Vector3> points = new List<Vector3>(); | |
List<BoneWeight> weights = new List<BoneWeight>(); | |
List<Matrix4x4> poses = new List<Matrix4x4>(); | |
int index = 0; | |
Transform t = new GameObject("joint " + index).transform; | |
t.parent = this.transform; | |
t.localRotation = Quaternion.identity; | |
t.localPosition = new Vector3(0, 0, 0); | |
Vector3 a = toLocal.MultiplyPoint(transform.position); | |
points.Add(a); | |
bones.Add(t); | |
poses.Add(t.worldToLocalMatrix * transform.localToWorldMatrix); | |
while (++index < m_steps) | |
{ | |
a = a + new Vector3(0, 1, 0) / (float)Mathf.Sqrt(index); | |
t = new GameObject("joint " + index).transform; | |
t.parent = bones[index - 1]; | |
t.localRotation = Quaternion.identity; | |
t.localPosition = new Vector3(0, 1, 0) / (float)Mathf.Sqrt(index); | |
points.Add(a); | |
bones.Add(t); | |
poses.Add(t.worldToLocalMatrix * transform.localToWorldMatrix); | |
} | |
tip = new GameObject("tip").transform; | |
tip.parent = bones[index - 1]; | |
tip.localRotation = Quaternion.identity; | |
tip.localPosition = new Vector3(0, 1, 0) / (float)Mathf.Sqrt(index); | |
a = a + new Vector3(0, 1, 0) / (float)Mathf.Sqrt(index); | |
points.Add(a); | |
List<int> indices = new List<int>(); | |
List<Vector3> vertices = new List<Vector3>(); | |
int counter = 0; | |
Vector3[] p = new Vector3[segments]; | |
for (int s = 0; s < segments; s++) | |
{ | |
p[s] = new Vector3(Mathf.Cos((float)s * Mathf.PI * 2 / (float)segments), 0, Mathf.Sin((float)s * Mathf.PI * 2 / (float)segments)); | |
p[s] *= 0.05f; | |
} | |
for (int i = 0; i < bones.Count; i++) | |
{ | |
for (int s = 0; s < segments; s++) | |
{ | |
vertices.Add(points[i] + p[s] / (float)Mathf.Sqrt(i + 1.0f) ); | |
indices.Add(counter++); | |
weights.Add(new BoneWeight() { boneIndex0 = i, weight0 = 1 }); | |
vertices.Add(points[i + 1] + p[s] / (float)Mathf.Sqrt(i + 2.0f)); | |
indices.Add(counter++); | |
weights.Add(new BoneWeight() { boneIndex0 = (i < bones.Count - 1) ? i + 1 : bones.Count - 1, weight0 = 1 }); | |
vertices.Add(points[i] + p[(s + 1) % segments] / (float)Mathf.Sqrt(i + 1.0f)); | |
indices.Add(counter++); | |
weights.Add(new BoneWeight() { boneIndex0 = i, weight0 = 1 }); | |
vertices.Add(points[i] + p[(s + 1) % segments] / (float)Mathf.Sqrt(i + 1.0f)); | |
indices.Add(counter++); | |
weights.Add(new BoneWeight() { boneIndex0 = i, weight0 = 1 }); | |
vertices.Add(points[i + 1] + p[s] / (float)Mathf.Sqrt(i + 2.0f)); | |
indices.Add(counter++); | |
weights.Add(new BoneWeight() { boneIndex0 = (i < bones.Count - 1) ? i + 1 : bones.Count - 1, weight0 = 1 }); | |
vertices.Add(points[i + 1] + p[(s + 1) % segments] / (float)Mathf.Sqrt(i + 2.0f)); | |
indices.Add(counter++); | |
weights.Add(new BoneWeight() { boneIndex0 = (i < bones.Count - 1) ? i + 1 : bones.Count - 1, weight0 = 1 }); | |
} | |
} | |
Mesh mesh = new Mesh(); | |
mesh.vertices = vertices.ToArray(); | |
mesh.triangles = indices.ToArray(); | |
mesh.RecalculateNormals(); | |
mesh.boneWeights = weights.ToArray(); | |
mesh.bindposes = poses.ToArray(); | |
skinnedMeshRenderer.bones = bones.ToArray(); | |
skinnedMeshRenderer.sharedMesh = mesh; | |
skinnedMeshRenderer.sharedMaterial = material; | |
lastBone = bones[bones.Count - 1]; | |
} | |
public void UpdateMesh() | |
{ | |
for (int i = 0; i < bones.Count; i++) | |
{ | |
Vector3 f = bones[i].parent.worldToLocalMatrix.MultiplyPoint(m_forceSource).normalized; | |
Vector3 up = bones[i].worldToLocalMatrix.MultiplyVector(bones[i].parent.up).normalized; | |
Vector3 v = f / ((float)m_steps - i) * m_forceModule; | |
Vector3 d = (up + v).normalized; | |
Quaternion rotation = Quaternion.FromToRotation(up, d); | |
bones[i].localRotation = rotation; | |
} | |
return; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment