Files
beyond/Assets/Scripts/Effects/WeaponTrail.cs
2024-11-20 15:21:28 +01:00

353 lines
12 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
namespace Beyond
{
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
[DisallowMultipleComponent]
public class WeaponTrail : MonoBehaviour
{
[SerializeField] private Transform m_tip;
[SerializeField] private Transform m_base;
private Mesh m_mesh;
[SerializeField] private int m_numFrames = 10;
private Transform m_parentWeapon;
private const int NUM_VERTICES = 2;
private int m_frameNum = 0;
private int m_triNum = 0;
private int[] m_triangles;
private Vector3[] m_vertices;
private Color[] m_colours;
private bThirdPersonInput m_tpInput;
private Renderer m_renderer;
private const int NUM_PREV_POINTS = 3;
private Vector3[] m_prevTip = new Vector3[NUM_PREV_POINTS], m_prevBase = new Vector3[NUM_PREV_POINTS];
[SerializeField] private int m_maxDivisions = 4;
[SerializeField] private float m_stripLength = 0.1f;
[ColorUsageAttribute(true, true, 0f, 8f, 0.125f, 3f)]
public Color m_colorMultiplier = Color.white;
public bool m_alwaysPlay = true;
// Start is called before the first frame update
void Start()
{
m_tpInput = Player.Instance.GetComponent<bThirdPersonInput>();
// transform.parent = null;
var meshFilter = GetComponent<MeshFilter>();
m_renderer = GetComponent<MeshRenderer>();
m_mesh = new Mesh();
m_renderer.shadowCastingMode = ShadowCastingMode.Off;
m_mesh.MarkDynamic();
meshFilter.mesh = m_mesh;
m_tip.transform.parent = transform.parent;
m_base.transform.parent = transform.parent;
m_parentWeapon = transform.parent;
transform.parent = null;
transform.position = Vector3.zero;
transform.rotation = Quaternion.identity;
transform.localScale = Vector3.one;
for (int i = 0; i < NUM_PREV_POINTS; i++)
{
m_prevTip[i] = m_tip.transform.position;
m_prevBase[i] = m_base.transform.position;
}
//m_vertices = new Vector3[m_numFrames * NUM_VERTICES];
m_vertices = new Vector3[m_numFrames * NUM_VERTICES];
m_colours = new Color[m_vertices.Length];
m_triangles = new int[(m_numFrames-1) * 6];
var basePos = m_base.transform.position;
var tipPos = m_tip.transform.position;
for (int i = 0; i < m_numFrames; i++)
{
int vdx = i * NUM_VERTICES;
m_vertices[vdx + 0] = basePos;
m_vertices[vdx + 1] = tipPos;
}
int numV = m_vertices.Length;
for (int i = 0; i < m_numFrames-1; i++)
{
int vdx = i * NUM_VERTICES;
int tdx = i * 6;
int v2 = (vdx + 2 )% numV;
int v3 = (vdx + 3 )% numV;
//int v2 = (vdx - 2 );//% numV;
//int v3 = (vdx - 1 );//% numV;
//if (v2 < 0) v2 += numV;
//if (v3 < 0) v3 += numV;
m_triangles[tdx + 0] = vdx + 0;
m_triangles[tdx + 1] = vdx + 1;
m_triangles[tdx + 2] = v2;
m_triangles[tdx + 3] = v2;
m_triangles[tdx + 4] = v3;
m_triangles[tdx + 5] = vdx + 1;
}
// m_mesh.vertices = m_vertices;
// m_mesh.triangles = m_triangles;
}
Vector3 CatmullRom(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, float s)
{
Vector3 res;
float s2, s3;
s2 = s * s;
s3 = s2 * s;
res = p1 * (-s3 + 2.0f * s2 - s) + p2 * (3.0f * s3 - 5.0f * s2 + 2.0f) + p3 * (-3.0f * s3 + 4.0f * s2 + s) + p4 * (s3 - s2);
res /= 2.0f;
return res;
}
bool PlayConditions()
{
bool playConditions = m_tpInput.cc.IsAnimatorTag("Attack") && m_parentWeapon.gameObject.activeInHierarchy;
return playConditions;
}
/*
void Update()
{
bool shouldPlay = PlayConditions() || m_alwaysPlay;
m_renderer.enabled = shouldPlay;
var basePos = m_base.transform.position;
var tipPos = m_tip.transform.position;
if (!shouldPlay)
{
for (int i = 0; i < NUM_PREV_POINTS; i++)
{
m_prevBase[i] = basePos;
m_prevTip[i] = tipPos;
}
}
else
{
Debug.Log("Attack!");
}
int numV = m_vertices.Length;
int idx = m_frameNum * NUM_VERTICES;
if (m_numDivisions > 1)
{
for (int d = 0; d < m_numDivisions; d++ )
{
idx = m_frameNum * NUM_VERTICES;
float t = (float) d / (float) m_numDivisions;
m_vertices[idx + 0] = CatmullRom(m_prevBase[1], m_prevBase[0], basePos, basePos, t);
m_vertices[idx + 1] = CatmullRom(m_prevTip[1], m_prevTip[0], tipPos, tipPos, t);
int tdx = m_frameNum * 6;
//int v2 = (idx + 2 );//% numV;
//int v3 = (idx + 3 );//% numV;
int v2 = (idx - 2 );//% numV;
int v3 = (idx - 1 );//% numV;
if (v2 < 0) v2 += numV;
if (v3 < 0) v3 += numV;
m_triangles[tdx + 0] = idx + 0;
m_triangles[tdx + 1] = idx + 1;
m_triangles[tdx + 2] = v2;
m_triangles[tdx + 3] = v2;
m_triangles[tdx + 4] = v3;
m_triangles[tdx + 5] = idx + 1;
m_frameNum++;
m_frameNum %= m_numFrames;
}
}
else
{
m_vertices[idx + 0] = basePos;
m_vertices[idx + 1] = tipPos;
m_vertices[idx + 2] = m_prevBase[0];
m_vertices[idx + 3] = m_prevTip[0];
int tdx = m_frameNum * 6;
int v2 = (idx +2 );//% numV;
int v3 = (idx +3 );//% numV;
if (v2 < 0) v2 += numV;
if (v3 < 0) v3 += numV;
m_triangles[tdx + 0] = idx + 0;
m_triangles[tdx + 1] = idx + 1;
m_triangles[tdx + 2] = v2;
m_triangles[tdx + 3] = v2;
m_triangles[tdx + 4] = v3;
m_triangles[tdx + 5] = idx + 1;
m_frameNum++;
m_frameNum %= m_numFrames;
}
//fill colours
Color colour = Color.white;
for (int i = 0; i < m_numFrames; i++)
{
//colour.a = (float) (i) / ((float) m_numFrames);
colour.a = (float) (m_numFrames - i) / ((float) m_numFrames);
int cnum = (m_frameNum - i) % m_numFrames;
if (cnum < 0) cnum += m_numFrames;
int cid = (cnum * NUM_VERTICES);
for (int j = 0; j < NUM_VERTICES; j++)
{
m_colours[cid + j] = colour;
}
}
m_mesh.vertices = m_vertices;
m_mesh.colors = m_colours;
//m_mesh.
m_mesh.triangles = m_triangles;
m_mesh.RecalculateBounds();
for (int i = 0; i < NUM_PREV_POINTS - 1; i++)
{
m_prevTip[i + 1] = m_prevTip[i];
m_prevBase[i + 1] = m_prevBase[i];
}
m_prevTip[0] = tipPos;
m_prevBase[0] = basePos;
}
*/
// Update is called once per frame
void AddStrip(Vector3 basePos, Vector3 tipPos)
{
int numV = m_vertices.Length;
int idx = m_frameNum * NUM_VERTICES;
m_vertices[idx + 0] = basePos;
m_vertices[idx + 1] = tipPos;
int tidx = m_triNum * 6;
int v2 = (idx - 2);
int v3 = (idx - 1);
if (v2 < 0) v2 += numV;
if (v3 < 0) v3 += numV;
m_triangles[tidx + 0] = idx + 0;
m_triangles[tidx + 1] = idx + 1;
m_triangles[tidx + 2] = v2;
m_triangles[tidx + 3] = v2;
m_triangles[tidx + 4] = v3;
m_triangles[tidx + 5] = idx + 1;
m_frameNum++;
m_frameNum %= m_numFrames;
m_triNum++;
m_triNum %= (m_numFrames - 1);
}
void FixedUpdate()
{
bool shouldPlay = PlayConditions() || m_alwaysPlay;
m_renderer.enabled = shouldPlay;
var basePos = m_base.transform.position;
var tipPos = m_tip.transform.position;
if (!shouldPlay)
{
if (Player.Instance.ActiveWeaponTrail == this)
{
Player.Instance.ActiveWeaponTrail = null;
}
for (int i = 0; i < NUM_PREV_POINTS; i++)
{
m_prevBase[i] = basePos;
m_prevTip[i] = tipPos;
}
AddStrip(basePos, tipPos);
return;
}
else
{
Player.Instance.ActiveWeaponTrail = this;
//Debug.Log("Attack!");
}
int numV = m_vertices.Length;
int idx = m_frameNum * NUM_VERTICES;
if (m_maxDivisions > 1)
{
float bdist = Vector3.Distance(m_prevBase[0], basePos);
float tdist = Vector3.Distance(m_prevTip[0], tipPos);
float dist = Mathf.Max(bdist, tdist);
int div = Mathf.CeilToInt(dist / m_stripLength);
div = Math.Min(div, m_maxDivisions);
//Debug.Log("Divisions: "+div);
for (int d = 0; d < div; d++ )
{
float t = (float) d / (float) div;
//var bp = CatmullRom(m_prevBase[1], m_prevBase[0], basePos, basePos, t);
//var tp = CatmullRom(m_prevTip[1], m_prevTip[0], tipPos, tipPos, t);
var bp = CatmullRom(m_prevBase[2], m_prevBase[1], m_prevBase[0], basePos, t);
var tp = CatmullRom(m_prevTip[2], m_prevTip[1], m_prevTip[0], tipPos, t);
AddStrip(bp, tp);
}
}
else
{
AddStrip(basePos, tipPos);
}
//fill colours
Color colour = m_colorMultiplier;
for (int i = 0; i < m_numFrames; i++)
{
//colour.a = (float) (i) / ((float) m_numFrames);
colour.a = (float) (m_numFrames - i) / ((float) m_numFrames);
int cnum = (m_frameNum - i-1) % m_numFrames;
if (cnum < 0) cnum += m_numFrames;
int cid = (cnum * NUM_VERTICES);
for (int j = 0; j < NUM_VERTICES; j++)
{
m_colours[cid + j] = colour;
}
}
m_mesh.vertices = m_vertices;
m_mesh.colors = m_colours;
//m_mesh.
m_mesh.triangles = m_triangles;
m_mesh.RecalculateBounds();
for (int i = 0; i < NUM_PREV_POINTS - 1; i++)
{
m_prevTip[i + 1] = m_prevTip[i];
m_prevBase[i + 1] = m_prevBase[i];
}
m_prevTip[0] = tipPos;
m_prevBase[0] = basePos;
}
}
}