Files
Amir_NutBolt_Updated/Assets/Dreamteck/Splines/Components/MeshGenerator.cs
2026-06-07 22:59:32 +08:00

441 lines
12 KiB
C#

using UnityEngine;
using System.Collections;
using System.Threading;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace Dreamteck.Splines
{
public class MeshGenerator : SplineUser
{
public float size
{
get { return _size; }
set
{
if (value != _size)
{
_size = value;
Rebuild();
} else _size = value;
}
}
public Color color
{
get { return _color; }
set
{
if (value != _color)
{
_color = value;
Rebuild();
}
}
}
public Vector3 offset
{
get { return _offset; }
set
{
if (value != _offset)
{
_offset = value;
Rebuild();
}
}
}
public NormalMethod normalMethod
{
get { return _normalMethod; }
set
{
if (value != _normalMethod)
{
_normalMethod = value;
Rebuild();
}
}
}
public bool calculateTangents
{
get { return _calculateTangents; }
set
{
if (value != _calculateTangents)
{
_calculateTangents = value;
Rebuild();
}
}
}
public float rotation
{
get { return _rotation; }
set
{
if (value != _rotation)
{
_rotation = value;
Rebuild();
}
}
}
public bool flipFaces
{
get { return _flipFaces; }
set
{
if (value != _flipFaces)
{
_flipFaces = value;
Rebuild();
}
}
}
public bool doubleSided
{
get { return _doubleSided; }
set
{
if (value != _doubleSided)
{
_doubleSided = value;
Rebuild();
}
}
}
public UVMode uvMode
{
get { return _uvMode; }
set
{
if (value != _uvMode)
{
_uvMode = value;
Rebuild();
}
}
}
public Vector2 uvScale
{
get { return _uvScale; }
set
{
if (value != _uvScale)
{
_uvScale = value;
Rebuild();
}
}
}
public Vector2 uvOffset
{
get { return _uvOffset; }
set
{
if (value != _uvOffset)
{
_uvOffset = value;
Rebuild();
}
}
}
public float uvRotation
{
get { return _uvRotation; }
set
{
if (value != _uvRotation)
{
_uvRotation = value;
Rebuild();
}
}
}
public bool baked
{
get
{
return _baked;
}
}
public enum UVMode { Clip, UniformClip, Clamp, UniformClamp }
public enum NormalMethod { Recalculate, SplineNormals }
[SerializeField]
[HideInInspector]
private bool _baked = false;
[SerializeField]
[HideInInspector]
private float _size = 1f;
[SerializeField]
[HideInInspector]
private Color _color = Color.white;
[SerializeField]
[HideInInspector]
private Vector3 _offset = Vector3.zero;
[SerializeField]
[HideInInspector]
private NormalMethod _normalMethod = NormalMethod.SplineNormals;
[SerializeField]
[HideInInspector]
private bool _calculateTangents = true;
[SerializeField]
[HideInInspector]
[Range(-360f, 360f)]
private float _rotation = 0f;
[SerializeField]
[HideInInspector]
private bool _flipFaces = false;
[SerializeField]
[HideInInspector]
private bool _doubleSided = false;
[SerializeField]
[HideInInspector]
private UVMode _uvMode = UVMode.Clip;
[SerializeField]
[HideInInspector]
private Vector2 _uvScale = Vector2.one;
[SerializeField]
[HideInInspector]
private Vector2 _uvOffset = Vector2.zero;
[SerializeField]
[HideInInspector]
private float _uvRotation = 0f;
[SerializeField]
[HideInInspector]
protected MeshCollider meshCollider;
[SerializeField]
[HideInInspector]
protected MeshFilter filter;
[SerializeField]
[HideInInspector]
protected MeshRenderer meshRenderer;
[SerializeField]
[HideInInspector]
protected TS_Mesh tsMesh = new TS_Mesh();
[SerializeField]
[HideInInspector]
protected Mesh mesh;
[HideInInspector]
public float colliderUpdateRate = 0.2f;
protected bool updateCollider = false;
protected float lastUpdateTime = 0f;
private float vDist = 0f;
protected static Vector2 uvs = Vector2.zero;
#if UNITY_EDITOR
public override void EditorAwake()
{
base.EditorAwake();
CloneMesh();
Awake();
}
public void Bake(bool makeStatic, bool lightmapUV)
{
if (mesh == null) return;
gameObject.isStatic = false;
UnityEditor.MeshUtility.Optimize(mesh);
if(spline != null) spline.Unsubscribe(this);
filter = GetComponent<MeshFilter>();
meshRenderer = GetComponent<MeshRenderer>();
filter.hideFlags = meshRenderer.hideFlags = HideFlags.None;
filter.sharedMesh = mesh;
if (lightmapUV) Unwrapping.GenerateSecondaryUVSet(filter.sharedMesh);
if (makeStatic) gameObject.isStatic = true;
_baked = true;
}
public void Unbake()
{
gameObject.isStatic = false;
_baked = false;
spline.Subscribe(this);
Rebuild();
}
#endif
protected override void Awake()
{
if (mesh == null) mesh = new Mesh();
base.Awake();
filter = GetComponent<MeshFilter>();
meshRenderer = GetComponent<MeshRenderer>();
meshCollider = GetComponent<MeshCollider>();
}
protected override void Reset()
{
base.Reset();
#if UNITY_EDITOR
MeshRenderer rend = GetComponent<MeshRenderer>();
bool materialFound = false;
for (int i = 0; i < rend.sharedMaterials.Length; i++)
{
if (rend.sharedMaterials[i] != null)
{
materialFound = true;
break;
}
}
if (!materialFound) rend.sharedMaterial = AssetDatabase.GetBuiltinExtraResource<Material>("Default-Diffuse.mat");
#endif
}
public void CloneMesh()
{
if (tsMesh != null) tsMesh = TS_Mesh.Copy(tsMesh);
else tsMesh = new TS_Mesh();
if (mesh != null) mesh = (Mesh)Instantiate(mesh);
else mesh = new Mesh();
}
public override void Rebuild()
{
if (_baked) return;
base.Rebuild();
}
public override void RebuildImmediate()
{
if (_baked) return;
base.RebuildImmediate();
}
protected override void OnEnable()
{
base.OnEnable();
}
protected override void OnDisable()
{
base.OnDisable();
}
protected override void OnDestroy()
{
base.OnDestroy();
MeshFilter filter = GetComponent<MeshFilter>();
MeshRenderer rend = GetComponent<MeshRenderer>();
if (filter != null) filter.hideFlags = HideFlags.None;
if (rend != null) rend.hideFlags = HideFlags.None;
}
public void UpdateCollider()
{
meshCollider = GetComponent<MeshCollider>();
if (meshCollider == null) meshCollider = gameObject.AddComponent<MeshCollider>();
meshCollider.sharedMesh = filter.sharedMesh;
}
protected override void LateRun()
{
if (_baked) return;
base.LateRun();
if (updateCollider)
{
if (meshCollider != null)
{
if (Time.time - lastUpdateTime >= colliderUpdateRate)
{
lastUpdateTime = Time.time;
updateCollider = false;
meshCollider.sharedMesh = filter.sharedMesh;
}
}
}
}
protected override void Build()
{
base.Build();
if (sampleCount > 0) BuildMesh();
}
protected override void PostBuild()
{
base.PostBuild();
WriteMesh();
}
protected virtual void BuildMesh()
{
//Logic for mesh generation, automatically called in the Build method
}
protected virtual void WriteMesh()
{
MeshUtility.InverseTransformMesh(tsMesh, trs);
if (_doubleSided) MeshUtility.MakeDoublesidedHalf(tsMesh);
else if(_flipFaces) MeshUtility.FlipFaces(tsMesh);
if (_calculateTangents) MeshUtility.CalculateTangents(tsMesh);
if(tsMesh.vertexCount > 64000) Debug.LogError("WARNING: The generated mesh for " + name + " has " + tsMesh.vertexCount + " vertices. The maximum vertex count for meshes in Unity is 64000. The mesh will not be updated.");
tsMesh.WriteMesh(ref mesh);
if (_normalMethod == 0) mesh.RecalculateNormals();
if (filter != null) filter.sharedMesh = mesh;
updateCollider = true;
}
protected virtual void AllocateMesh(int vertexCount, int trisCount)
{
if (_doubleSided)
{
vertexCount *= 2;
trisCount *= 2;
}
if (tsMesh.vertexCount != vertexCount)
{
tsMesh.vertices = new Vector3[vertexCount];
tsMesh.normals = new Vector3[vertexCount];
tsMesh.tangents = new Vector4[vertexCount];
tsMesh.colors = new Color[vertexCount];
tsMesh.uv = new Vector2[vertexCount];
}
if (tsMesh.triangles.Length != trisCount) tsMesh.triangles = new int[trisCount];
}
protected void ResetUVDistance()
{
vDist = 0f;
if (uvMode == UVMode.UniformClip) vDist = spline.CalculateLength(0.0, GetSampleRaw(0).percent);
}
protected void AddUVDistance(int sampleIndex)
{
if (sampleIndex == 0) return;
vDist += Vector3.Distance(GetSampleRaw(sampleIndex).position, GetSampleRaw(sampleIndex - 1).position);
}
protected void CalculateUVs(double percent, float u)
{
uvs.x = u * _uvScale.x - _uvOffset.x;
switch (uvMode)
{
case UVMode.Clip: uvs.y = (float)percent * _uvScale.y - _uvOffset.y; break;
case UVMode.Clamp: uvs.y = (float)DMath.InverseLerp(clipFrom, clipTo, percent) * _uvScale.y - _uvOffset.y; break;
case UVMode.UniformClamp: uvs.y = vDist * _uvScale.y / (float)span - _uvOffset.y; break;
default: uvs.y = vDist * _uvScale.y - _uvOffset.y; break;
}
}
}
}