rabidus-test/Assets/Dreamteck/Splines/Components/SplineMeshChannel.cs

1489 lines
53 KiB
C#
Raw Permalink Normal View History

2023-07-24 16:38:13 +03:00
using UnityEngine;
using System.Collections.Generic;
namespace Dreamteck.Splines
{
public partial class SplineMesh : MeshGenerator
{
[System.Serializable]
public class Channel
{
public delegate float FloatHandler(double percent);
public delegate Vector2 Vector2Handler(double percent);
public delegate Vector3 Vector3Handler(double percent);
public delegate Quaternion QuaternionHandler(double percent);
public string name = "Channel";
public enum Type { Extrude, Place }
public enum UVOverride { None, ClampU, ClampV, UniformU, UniformV }
private System.Random iterationRandom;
[SerializeField]
[HideInInspector]
private int _iterationSeed = 0;
[SerializeField]
[HideInInspector]
private int _offsetSeed = 0;
private System.Random _offsetRandom;
private Vector2Handler _offsetHandler = null;
[SerializeField]
[HideInInspector]
private int _rotationSeed = 0;
private System.Random _rotationRandom;
private QuaternionHandler _placeRotationHandler = null;
private FloatHandler _extrudeRotationHandler = null;
[SerializeField]
[HideInInspector]
private int _scaleSeed = 0;
private System.Random _scaleRandom;
private Vector3Handler _scaleHandler = null;
[SerializeField]
internal SplineMesh owner = null;
[SerializeField]
[HideInInspector]
private List<MeshDefinition> meshes = new List<MeshDefinition>();
[SerializeField]
[HideInInspector]
private double _clipFrom = 0.0;
[SerializeField]
[HideInInspector]
private double _clipTo = 1.0;
[SerializeField]
[HideInInspector]
private bool _randomOrder = false;
[SerializeField]
[HideInInspector]
private UVOverride _overrideUVs = UVOverride.None;
[SerializeField]
[HideInInspector]
private Vector2 _uvScale = Vector2.one;
[SerializeField]
[HideInInspector]
private Vector2 _uvOffset = Vector2.zero;
[SerializeField]
[HideInInspector]
private bool _overrideNormal = false;
[SerializeField]
[HideInInspector]
private Vector3 _customNormal = Vector3.up;
[SerializeField]
[HideInInspector]
private Type _type = Type.Extrude;
[SerializeField]
[HideInInspector]
private int _count = 1;
[SerializeField]
[HideInInspector]
private bool _autoCount = false;
[SerializeField]
[HideInInspector]
private double _spacing = 0.0;
[SerializeField]
[HideInInspector]
private bool _randomRotation = false;
[SerializeField]
[HideInInspector]
private Vector3 _minRotation = Vector3.zero;
[SerializeField]
[HideInInspector]
private Vector3 _maxRotation = Vector3.zero;
[SerializeField]
[HideInInspector]
private bool _randomOffset = false;
[SerializeField]
[HideInInspector]
private Vector2 _minOffset = Vector2.one;
[SerializeField]
[HideInInspector]
private Vector2 _maxOffset = Vector2.one;
[SerializeField]
[HideInInspector]
private bool _randomScale = false;
[SerializeField]
[HideInInspector]
private bool _uniformRandomScale = false;
[SerializeField]
[HideInInspector]
private Vector3 _minScale = Vector3.one;
[SerializeField]
[HideInInspector]
private Vector3 _maxScale = Vector3.one;
private int iterator = 0;
[SerializeField]
[HideInInspector]
private bool _overrideMaterialID = false;
[SerializeField]
[HideInInspector]
private int _targetMaterialID = 0;
[SerializeField]
[HideInInspector]
protected MeshScaleModifier _scaleModifier = new MeshScaleModifier();
public double clipFrom
{
get { return _clipFrom; }
set
{
if (value != _clipFrom)
{
_clipFrom = value;
Rebuild();
}
}
}
public double clipTo
{
get { return _clipTo; }
set
{
if (value != _clipTo)
{
_clipTo = value;
Rebuild();
}
}
}
public bool randomOffset
{
get { return _randomOffset; }
set
{
if (value != _randomOffset)
{
_randomOffset = value;
Rebuild();
}
}
}
public Vector2Handler offsetHandler
{
get { return _offsetHandler; }
set
{
if (value != _offsetHandler)
{
_offsetHandler = value;
Rebuild();
}
}
}
public bool overrideMaterialID
{
get { return _overrideMaterialID; }
set
{
if (value != _overrideMaterialID)
{
_overrideMaterialID = value;
Rebuild();
}
}
}
public int targetMaterialID
{
get { return _targetMaterialID; }
set
{
if (value != _targetMaterialID)
{
_targetMaterialID = value;
Rebuild();
}
}
}
public bool randomRotation
{
get { return _randomRotation; }
set
{
if (value != _randomRotation)
{
_randomRotation = value;
Rebuild();
}
}
}
public QuaternionHandler placeRotationHandler
{
get { return _placeRotationHandler; }
set
{
if (value != _placeRotationHandler)
{
_placeRotationHandler = value;
Rebuild();
}
}
}
public FloatHandler extrudeRotationHandler
{
get { return _extrudeRotationHandler; }
set
{
if (value != _extrudeRotationHandler)
{
_extrudeRotationHandler = value;
Rebuild();
}
}
}
public bool randomScale
{
get { return _randomScale; }
set
{
if (value != _randomScale)
{
_randomScale = value;
Rebuild();
}
}
}
public Vector3Handler scaleHandler
{
get { return _scaleHandler; }
set
{
if (value != _scaleHandler)
{
_scaleHandler = value;
Rebuild();
}
}
}
public bool uniformRandomScale
{
get { return _uniformRandomScale; }
set
{
if (value != _uniformRandomScale)
{
_uniformRandomScale = value;
Rebuild();
}
}
}
public int offsetSeed
{
get { return _offsetSeed; }
set
{
if (value != _offsetSeed)
{
_offsetSeed = value;
Rebuild();
}
}
}
public int rotationSeed
{
get { return _rotationSeed; }
set
{
if (value != _rotationSeed)
{
_rotationSeed = value;
Rebuild();
}
}
}
public int scaleSeed
{
get { return _scaleSeed; }
set
{
if (value != _scaleSeed)
{
_scaleSeed = value;
Rebuild();
}
}
}
public double spacing
{
get { return _spacing; }
set
{
if (value != _spacing)
{
_spacing = value;
Rebuild();
}
}
}
public Vector2 minOffset
{
get { return _minOffset; }
set
{
if (value != _minOffset)
{
_minOffset = value;
Rebuild();
}
}
}
public Vector2 maxOffset
{
get { return _maxOffset; }
set
{
if (value != _maxOffset)
{
_maxOffset = value;
Rebuild();
}
}
}
public Vector3 minRotation
{
get { return _minRotation; }
set
{
if (value != _minRotation)
{
_minRotation = value;
Rebuild();
}
}
}
public Vector3 maxRotation
{
get { return _maxRotation; }
set
{
if (value != _maxRotation)
{
_maxRotation = value;
Rebuild();
}
}
}
public Vector3 minScale
{
get { return _minScale; }
set
{
if (value != _minScale)
{
_minScale = value;
Rebuild();
}
}
}
public Vector3 maxScale
{
get { return _maxScale; }
set
{
if (value != _maxScale)
{
_maxScale = value;
Rebuild();
}
}
}
public Type type
{
get { return _type; }
set
{
if (value != _type)
{
_type = value;
Rebuild();
}
}
}
public bool randomOrder
{
get { return _randomOrder; }
set
{
if (value != _randomOrder)
{
_randomOrder = value;
Rebuild();
}
}
}
public int randomSeed
{
get { return _iterationSeed; }
set
{
if (value != _iterationSeed)
{
_iterationSeed = value;
if (_randomOrder) Rebuild();
}
}
}
public int count
{
get { return _count; }
set
{
if (value != _count)
{
_count = value;
if (_count < 1) _count = 1;
Rebuild();
}
}
}
public bool autoCount
{
get { return _autoCount; }
set
{
if (value != _autoCount)
{
_autoCount = value;
Rebuild();
}
}
}
public UVOverride overrideUVs
{
get { return _overrideUVs; }
set
{
if (value != _overrideUVs)
{
_overrideUVs = value;
Rebuild();
}
}
}
public Vector2 uvOffset
{
get { return _uvOffset; }
set
{
if (value != _uvOffset)
{
_uvOffset = value;
Rebuild();
}
}
}
public Vector2 uvScale
{
get { return _uvScale; }
set
{
if (value != _uvScale)
{
_uvScale = value;
Rebuild();
}
}
}
public bool overrideNormal
{
get { return _overrideNormal; }
set
{
if (value != _overrideNormal)
{
_overrideNormal = value;
Rebuild();
}
}
}
public Vector3 customNormal
{
get { return _customNormal; }
set
{
if (value != _customNormal)
{
_customNormal = value;
Rebuild();
}
}
}
public MeshScaleModifier scaleModifier
{
get
{
return _scaleModifier;
}
}
public Channel(string n, SplineMesh parent)
{
name = n;
owner = parent;
Init();
}
public Channel(string n, Mesh inputMesh, SplineMesh parent)
{
name = n;
owner = parent;
meshes.Add(new MeshDefinition(inputMesh));
Init();
Rebuild();
}
void Init()
{
_minScale = _maxScale = Vector3.one;
_minOffset = _maxOffset = Vector3.zero;
_minRotation = _maxRotation = Vector3.zero;
}
public void CopyTo(Channel target)
{
target.meshes.Clear();
for (int i = 0; i < meshes.Count; i++) target.meshes.Add(meshes[i].Copy());
target._clipFrom = _clipFrom;
target._clipTo = _clipTo;
target._customNormal = _customNormal;
target._iterationSeed = _iterationSeed;
target._minOffset = _minOffset;
target._minRotation = _minRotation;
target._minScale = _minScale;
target._maxOffset = _maxOffset;
target._maxRotation = _maxRotation;
target._maxScale = _maxScale;
target._randomOffset = _randomOffset;
target._randomRotation = _randomRotation;
target._randomScale = _randomScale;
target._offsetSeed = _offsetSeed;
target._offsetHandler = _offsetHandler;
target._rotationSeed = _rotationSeed;
target._placeRotationHandler = _placeRotationHandler;
target._extrudeRotationHandler = _extrudeRotationHandler;
target._scaleSeed = _scaleSeed;
target._scaleHandler = _scaleHandler;
target._iterationSeed = _iterationSeed;
target._count = _count;
target._spacing = _spacing;
target._overrideUVs = _overrideUVs;
target._type = _type;
target._overrideMaterialID = _overrideMaterialID;
target._targetMaterialID = _targetMaterialID;
target._overrideNormal = _overrideNormal;
}
public int GetMeshCount()
{
return meshes.Count;
}
public void SwapMeshes(int a, int b)
{
if (a < 0 || a >= meshes.Count || b < 0 || b >= meshes.Count) return;
MeshDefinition temp = meshes[b];
meshes[b] = meshes[a];
meshes[a] = temp;
Rebuild();
}
public void DuplicateMesh(int index)
{
if (index < 0 || index >= meshes.Count) return;
meshes.Add(meshes[index].Copy());
Rebuild();
}
public MeshDefinition GetMesh(int index)
{
return meshes[index];
}
public void AddMesh(Mesh input)
{
meshes.Add(new MeshDefinition(input));
Rebuild();
}
public void AddMesh(MeshDefinition meshDefinition)
{
if (!meshes.Contains(meshDefinition))
{
meshes.Add(meshDefinition);
Rebuild();
}
}
public void RemoveMesh(int index)
{
meshes.RemoveAt(index);
Rebuild();
}
public void ResetIteration()
{
if (_randomOrder) iterationRandom = new System.Random(_iterationSeed);
if (_randomOffset) _offsetRandom = new System.Random(_offsetSeed);
if (_randomRotation) _rotationRandom = new System.Random(_rotationSeed);
if (_randomScale) _scaleRandom = new System.Random(_scaleSeed);
iterator = 0;
}
public (Vector2, Quaternion, Vector3) GetCustomPlaceValues(double percent)
{
(Vector2, Quaternion, Vector3) values = (Vector2.zero, Quaternion.identity, Vector3.one);
if (_offsetHandler != null)
{
values.Item1 = _offsetHandler(percent);
}
if (_placeRotationHandler != null)
{
values.Item2 = _placeRotationHandler(percent);
}
if (_scaleHandler != null)
{
values.Item3 = _scaleHandler(percent);
}
return values;
}
public (Vector2, float, Vector3) GetCustomExtrudeValues(double percent)
{
(Vector2, float, Vector3) values = (Vector2.zero, 0f, Vector3.one);
if (_offsetHandler != null)
{
values.Item1 = _offsetHandler(percent);
}
if (_extrudeRotationHandler != null)
{
values.Item2 = _extrudeRotationHandler(percent);
}
if (_scaleHandler != null)
{
values.Item3 = _scaleHandler(percent);
}
return values;
}
public Vector2 NextRandomOffset()
{
if (_randomOffset) return new Vector2(Mathf.Lerp(_minOffset.x, _maxOffset.x, (float)_offsetRandom.NextDouble()), Mathf.Lerp(_minOffset.y, _maxOffset.y, (float)_offsetRandom.NextDouble()));
return _minOffset;
}
public Quaternion NextRandomQuaternion()
{
if (_randomRotation) return Quaternion.Euler(new Vector3(Mathf.Lerp(_minRotation.x, _maxRotation.x, (float)_rotationRandom.NextDouble()), Mathf.Lerp(_minRotation.y, _maxRotation.y, (float)_rotationRandom.NextDouble()), Mathf.Lerp(_minRotation.z, _maxRotation.z, (float)_rotationRandom.NextDouble())));
return Quaternion.Euler(_minRotation);
}
public float NextRandomAngle()
{
if (_randomRotation) return Mathf.Lerp(_minRotation.z, _maxRotation.z, (float)_rotationRandom.NextDouble());
return _minRotation.z;
}
public Vector3 NextRandomScale()
{
if (_randomScale)
{
if (_uniformRandomScale) return Vector3.Lerp(new Vector3(_minScale.x, _minScale.y, 1f), new Vector3(_maxScale.x, _maxScale.y, 1f), (float)_scaleRandom.NextDouble());
return new Vector3(Mathf.Lerp(_minScale.x, _maxScale.x, (float)_scaleRandom.NextDouble()), Mathf.Lerp(_minScale.y, _maxScale.y, (float)_scaleRandom.NextDouble()), 1f);
}
return new Vector3(_minScale.x, _minScale.y, 1f);
}
public Vector3 NextPlaceScale()
{
if (_randomScale)
{
if (_uniformRandomScale) return Vector3.Lerp(_minScale, _maxScale, (float)_scaleRandom.NextDouble());
return new Vector3(Mathf.Lerp(_minScale.x, _maxScale.x, (float)_scaleRandom.NextDouble()), Mathf.Lerp(_minScale.y, _maxScale.y, (float)_scaleRandom.NextDouble()), Mathf.Lerp(_minScale.z, _maxScale.z, (float)_scaleRandom.NextDouble()));
}
return _minScale;
}
public MeshDefinition NextMesh()
{
if (_randomOrder) return meshes[iterationRandom.Next(meshes.Count)];
else
{
if (iterator >= meshes.Count) iterator = 0;
return meshes[iterator++];
}
}
internal void Rebuild()
{
if (owner != null) owner.Rebuild();
}
void Refresh()
{
for (int i = 0; i < meshes.Count; i++) meshes[i].Refresh();
Rebuild();
}
[System.Serializable]
public struct BoundsSpacing
{
public float front;
public float back;
}
[System.Serializable]
public class MeshDefinition
{
public enum MirrorMethod { None, X, Y, Z }
[SerializeField]
[HideInInspector]
public Vector3[] vertices = new Vector3[0];
[SerializeField]
[HideInInspector]
public Vector3[] normals = new Vector3[0];
[SerializeField]
[HideInInspector]
public Vector4[] tangents = new Vector4[0];
[SerializeField]
[HideInInspector]
public Color[] colors = new Color[0];
[SerializeField]
[HideInInspector]
public Vector2[] uv = new Vector2[0];
[SerializeField]
[HideInInspector]
public Vector2[] uv2 = new Vector2[0];
[SerializeField]
[HideInInspector]
public Vector2[] uv3 = new Vector2[0];
[SerializeField]
[HideInInspector]
public Vector2[] uv4 = new Vector2[0];
[SerializeField]
[HideInInspector]
public int[] triangles = new int[0];
[SerializeField]
[HideInInspector]
public List<Submesh> subMeshes = new List<Submesh>();
[SerializeField]
[HideInInspector]
public TS_Bounds bounds = new TS_Bounds(Vector3.zero, Vector3.zero);
[SerializeField]
[HideInInspector]
public List<VertexGroup> vertexGroups = new List<VertexGroup>();
[SerializeField]
[HideInInspector]
private Mesh _mesh = null;
[SerializeField]
[HideInInspector]
private Vector3 _rotation = Vector3.zero;
[SerializeField]
[HideInInspector]
private Vector3 _offset = Vector3.zero;
[SerializeField]
[HideInInspector]
private Vector3 _scale = Vector3.one;
[SerializeField]
[HideInInspector]
private Vector2 _uvScale = Vector2.one;
[SerializeField]
[HideInInspector]
private Vector2 _uvOffset = Vector2.zero;
[SerializeField]
[HideInInspector]
private float _uvRotation = 0f;
[SerializeField]
[HideInInspector]
private MirrorMethod _mirror = MirrorMethod.None;
[SerializeField]
[HideInInspector]
public BoundsSpacing _spacing = new BoundsSpacing();
[SerializeField]
[HideInInspector]
private float _vertexGroupingMargin = 0f;
[SerializeField]
[HideInInspector]
private bool _removeInnerFaces = false;
[SerializeField]
[HideInInspector]
private bool _flipFaces = false;
[SerializeField]
[HideInInspector]
private bool _doubleSided = false;
public Mesh mesh
{
get
{
return _mesh;
}
set
{
if (_mesh != value)
{
_mesh = value;
Refresh();
}
}
}
public Vector3 rotation
{
get
{
return _rotation;
}
set
{
if (rotation != value)
{
_rotation = value;
Refresh();
}
}
}
public Vector3 offset
{
get
{
return _offset;
}
set
{
if (_offset != value)
{
_offset = value;
Refresh();
}
}
}
public Vector3 scale
{
get
{
return _scale;
}
set
{
if (_scale != value)
{
_scale = value;
Refresh();
}
}
}
public BoundsSpacing spacing
{
get
{
return _spacing;
}
set
{
if (_spacing.back != value.back || _spacing.front != value.front)
{
_spacing = value;
Refresh();
}
}
}
public Vector2 uvScale
{
get
{
return _uvScale;
}
set
{
if (_uvScale != value)
{
_uvScale = value;
Refresh();
}
}
}
public Vector2 uvOffset
{
get
{
return _uvOffset;
}
set
{
if (_uvOffset != value)
{
_uvOffset = value;
Refresh();
}
}
}
public float uvRotation
{
get
{
return _uvRotation;
}
set
{
if (_uvRotation != value)
{
_uvRotation = value;
Refresh();
}
}
}
public float vertexGroupingMargin
{
get
{
return _vertexGroupingMargin;
}
set
{
if (_vertexGroupingMargin != value)
{
_vertexGroupingMargin = value;
Refresh();
}
}
}
public MirrorMethod mirror
{
get { return _mirror; }
set
{
if (_mirror != value)
{
_mirror = value;
Refresh();
}
}
}
public bool removeInnerFaces
{
get { return _removeInnerFaces; }
set
{
if (_removeInnerFaces != value)
{
_removeInnerFaces = value;
Refresh();
}
}
}
public bool flipFaces
{
get { return _flipFaces; }
set
{
if (_flipFaces != value)
{
_flipFaces = value;
Refresh();
}
}
}
public bool doubleSided
{
get { return _doubleSided; }
set
{
if (_doubleSided != value)
{
_doubleSided = value;
Refresh();
}
}
}
internal MeshDefinition Copy()
{
MeshDefinition target = new MeshDefinition(_mesh);
target.vertices = new Vector3[vertices.Length];
target.normals = new Vector3[normals.Length];
target.colors = new Color[colors.Length];
target.tangents = new Vector4[tangents.Length];
target.uv = new Vector2[uv.Length];
target.uv2 = new Vector2[uv2.Length];
target.uv3 = new Vector2[uv3.Length];
target.uv4 = new Vector2[uv4.Length];
target.triangles = new int[triangles.Length];
vertices.CopyTo(target.vertices, 0);
normals.CopyTo(target.normals, 0);
colors.CopyTo(target.colors, 0);
tangents.CopyTo(target.tangents, 0);
uv.CopyTo(target.uv, 0);
uv2.CopyTo(target.uv2, 0);
uv3.CopyTo(target.uv3, 0);
uv4.CopyTo(target.uv4, 0);
triangles.CopyTo(target.triangles, 0);
target.bounds = new TS_Bounds(bounds.min, bounds.max);
target.subMeshes = new List<Submesh>();
for (int i = 0; i < subMeshes.Count; i++)
{
target.subMeshes.Add(new Submesh(new int[subMeshes[i].triangles.Length]));
subMeshes[i].triangles.CopyTo(target.subMeshes[target.subMeshes.Count - 1].triangles, 0);
}
target._mirror = _mirror;
target._offset = _offset;
target._rotation = _rotation;
target._scale = _scale;
target._uvOffset = _uvOffset;
target._uvScale = _uvScale;
target._uvRotation = _uvRotation;
target._flipFaces = _flipFaces;
target._doubleSided = _doubleSided;
return target;
}
public MeshDefinition(Mesh input)
{
_mesh = input;
Refresh();
}
public void Refresh()
{
if (_mesh == null)
{
vertices = new Vector3[0];
normals = new Vector3[0];
colors = new Color[0];
uv = new Vector2[0];
uv2 = new Vector2[0];
uv3 = new Vector2[0];
uv4 = new Vector2[0];
tangents = new Vector4[0];
triangles = new int[0];
subMeshes = new List<Submesh>();
vertexGroups = new List<VertexGroup>();
return;
}
if (vertices.Length != _mesh.vertexCount) vertices = new Vector3[_mesh.vertexCount];
if (normals.Length != _mesh.normals.Length) normals = new Vector3[_mesh.normals.Length];
if (colors.Length != _mesh.colors.Length) colors = new Color[_mesh.colors.Length];
if (uv.Length != _mesh.uv.Length) uv = new Vector2[_mesh.uv.Length];
if (uv2.Length != _mesh.uv2.Length) uv2 = new Vector2[_mesh.uv2.Length];
if (uv3.Length != _mesh.uv3.Length) uv3 = new Vector2[_mesh.uv3.Length];
if (uv4.Length != _mesh.uv4.Length) uv4 = new Vector2[_mesh.uv4.Length];
if (tangents.Length != _mesh.tangents.Length) tangents = new Vector4[_mesh.tangents.Length];
if (triangles.Length != _mesh.triangles.Length) triangles = new int[_mesh.triangles.Length];
vertices = _mesh.vertices;
normals = _mesh.normals;
colors = _mesh.colors;
uv = _mesh.uv;
uv2 = _mesh.uv2;
uv3 = _mesh.uv3;
uv4 = _mesh.uv4;
tangents = _mesh.tangents;
triangles = _mesh.triangles;
colors = _mesh.colors;
while (subMeshes.Count > _mesh.subMeshCount) subMeshes.RemoveAt(0);
while (subMeshes.Count < _mesh.subMeshCount) subMeshes.Add(new Submesh(new int[0]));
for (int i = 0; i < subMeshes.Count; i++) subMeshes[i].triangles = _mesh.GetTriangles(i);
if (colors.Length != vertices.Length)
{
colors = new Color[vertices.Length];
for (int i = 0; i < colors.Length; i++) colors[i] = Color.white;
}
Mirror();
if (_doubleSided) DoubleSided();
else if (_flipFaces) FlipFaces();
TransformVertices();
CalculateBounds();
if (_removeInnerFaces) RemoveInnerFaces();
GroupVertices();
}
void RemoveInnerFaces()
{
float min = float.MaxValue, max = 0f;
for (int i = 0; i < vertices.Length; i++)
{
if (vertices[i].z < min) min = vertices[i].z;
if (vertices[i].z > max) max = vertices[i].z;
}
for (int i = 0; i < subMeshes.Count; i++)
{
List<int> newTris = new List<int>();
for (int j = 0; j < subMeshes[i].triangles.Length; j += 3)
{
bool innerMax = true, innerMin = true;
for (int k = j; k < j + 3; k++)
{
int index = subMeshes[i].triangles[k];
if (!Mathf.Approximately(vertices[index].z, max)) innerMax = false;
if (!Mathf.Approximately(vertices[index].z, min)) innerMin = false;
}
if (!innerMax && !innerMin)
{
newTris.Add(subMeshes[i].triangles[j]);
newTris.Add(subMeshes[i].triangles[j + 1]);
newTris.Add(subMeshes[i].triangles[j + 2]);
}
}
subMeshes[i].triangles = newTris.ToArray();
}
}
void FlipFaces()
{
TS_Mesh temp = new TS_Mesh();
temp.normals = normals;
temp.tangents = tangents;
temp.triangles = triangles;
for (int i = 0; i < subMeshes.Count; i++) temp.subMeshes.Add(subMeshes[i].triangles);
MeshUtility.FlipFaces(temp);
}
void DoubleSided()
{
TS_Mesh temp = new TS_Mesh();
temp.vertices = vertices;
temp.normals = normals;
temp.tangents = tangents;
temp.colors = colors;
temp.uv = uv;
temp.uv2 = uv2;
temp.uv3 = uv3;
temp.uv4 = uv4;
temp.triangles = triangles;
for (int i = 0; i < subMeshes.Count; i++) temp.subMeshes.Add(subMeshes[i].triangles);
MeshUtility.MakeDoublesided(temp);
vertices = temp.vertices;
normals = temp.normals;
tangents = temp.tangents;
colors = temp.colors;
uv = temp.uv;
uv2 = temp.uv2;
uv3 = temp.uv3;
uv4 = temp.uv4;
triangles = temp.triangles;
for (int i = 0; i < subMeshes.Count; i++) subMeshes[i].triangles = temp.subMeshes[i];
}
public void Write(TS_Mesh target, int forceMaterialId = -1)
{
if (target.vertices.Length != vertices.Length) target.vertices = new Vector3[vertices.Length];
if (target.normals.Length != normals.Length) target.normals = new Vector3[normals.Length];
if (target.colors.Length != colors.Length) target.colors = new Color[colors.Length];
if (target.uv.Length != uv.Length) target.uv = new Vector2[uv.Length];
if (target.uv2.Length != uv2.Length) target.uv2 = new Vector2[uv2.Length];
if (target.uv3.Length != uv3.Length) target.uv3 = new Vector2[uv3.Length];
if (target.uv4.Length != uv4.Length) target.uv4 = new Vector2[uv4.Length];
if (target.tangents.Length != tangents.Length) target.tangents = new Vector4[tangents.Length];
if (target.triangles.Length != triangles.Length) target.triangles = new int[triangles.Length];
vertices.CopyTo(target.vertices, 0);
normals.CopyTo(target.normals, 0);
colors.CopyTo(target.colors, 0);
uv.CopyTo(target.uv, 0);
uv2.CopyTo(target.uv2, 0);
uv3.CopyTo(target.uv3, 0);
uv4.CopyTo(target.uv4, 0);
tangents.CopyTo(target.tangents, 0);
triangles.CopyTo(target.triangles, 0);
if (target.subMeshes == null) target.subMeshes = new List<int[]>();
if (forceMaterialId >= 0)
{
while (target.subMeshes.Count > forceMaterialId + 1) target.subMeshes.RemoveAt(0);
while (target.subMeshes.Count < forceMaterialId + 1) target.subMeshes.Add(new int[0]);
for (int i = 0; i < target.subMeshes.Count; i++)
{
if (i != forceMaterialId)
{
if (target.subMeshes[i].Length > 0) target.subMeshes[i] = new int[0];
}
else
{
if (target.subMeshes[i].Length != triangles.Length) target.subMeshes[i] = new int[triangles.Length];
triangles.CopyTo(target.subMeshes[i], 0);
}
}
}
else
{
while (target.subMeshes.Count > subMeshes.Count) target.subMeshes.RemoveAt(0);
while (target.subMeshes.Count < subMeshes.Count) target.subMeshes.Add(new int[0]);
for (int i = 0; i < subMeshes.Count; i++)
{
if (subMeshes[i].triangles.Length != target.subMeshes[i].Length) target.subMeshes[i] = new int[subMeshes[i].triangles.Length];
subMeshes[i].triangles.CopyTo(target.subMeshes[i], 0);
}
}
}
void CalculateBounds()
{
Vector3 min = Vector3.zero;
Vector3 max = Vector3.zero;
for (int i = 0; i < vertices.Length; i++)
{
if (vertices[i].x < min.x) min.x = vertices[i].x;
else if (vertices[i].x > max.x) max.x = vertices[i].x;
if (vertices[i].y < min.y) min.y = vertices[i].y;
else if (vertices[i].y > max.y) max.y = vertices[i].y;
if (vertices[i].z < min.z) min.z = vertices[i].z;
else if (vertices[i].z > max.z) max.z = vertices[i].z;
}
min.z -= spacing.back;
max.z += spacing.front;
bounds.CreateFromMinMax(min, max);
}
private void Mirror()
{
if (_mirror == MirrorMethod.None) return;
switch (_mirror)
{
case MirrorMethod.X:
for (int i = 0; i < vertices.Length; i++)
{
vertices[i].x *= -1f;
normals[i].x = -normals[i].x;
}
break;
case MirrorMethod.Y:
for (int i = 0; i < vertices.Length; i++)
{
vertices[i].y *= -1f;
normals[i].y = -normals[i].y;
}
break;
case MirrorMethod.Z:
for (int i = 0; i < vertices.Length; i++)
{
vertices[i].z *= -1f;
normals[i].z = -normals[i].z;
}
break;
}
for (int i = 0; i < triangles.Length; i += 3)
{
int temp = triangles[i];
triangles[i] = triangles[i + 2];
triangles[i + 2] = temp;
}
for (int i = 0; i < subMeshes.Count; i++)
{
for (int j = 0; j < subMeshes[i].triangles.Length; j += 3)
{
int temp = subMeshes[i].triangles[j];
subMeshes[i].triangles[j] = subMeshes[i].triangles[j + 2];
subMeshes[i].triangles[j + 2] = temp;
}
}
CalculateTangents();
}
void TransformVertices()
{
Matrix4x4 vertexMatrix = new Matrix4x4();
vertexMatrix.SetTRS(_offset, Quaternion.Euler(_rotation), _scale);
Matrix4x4 normalMatrix = vertexMatrix.inverse.transpose;
for (int i = 0; i < vertices.Length; i++)
{
vertices[i] = vertexMatrix.MultiplyPoint3x4(vertices[i]);
normals[i] = normalMatrix.MultiplyVector(normals[i]).normalized;
}
for (int i = 0; i < tangents.Length; i++) tangents[i] = normalMatrix.MultiplyVector(tangents[i]);
for (int i = 0; i < uv.Length; i++)
{
uv[i].x *= _uvScale.x;
uv[i].y *= _uvScale.y;
uv[i] += _uvOffset;
uv[i] = Quaternion.AngleAxis(uvRotation, Vector3.forward) * uv[i];
}
}
void GroupVertices()
{
vertexGroups = new List<VertexGroup>();
for (int i = 0; i < vertices.Length; i++)
{
float value = vertices[i].z;
double percent = DMath.Clamp01(DMath.InverseLerp(bounds.min.z, bounds.max.z, value));
int index = FindInsertIndex(vertices[i], value);
if (index >= vertexGroups.Count) vertexGroups.Add(new VertexGroup(value, percent, new int[] { i }));
else
{
float valueDelta = Mathf.Abs(vertexGroups[index].value - value);
if (valueDelta < vertexGroupingMargin || Mathf.Approximately(valueDelta, vertexGroupingMargin)) vertexGroups[index].AddId(i);
else if (vertexGroups[index].value < value) vertexGroups.Insert(index, new VertexGroup(value, percent, new int[] { i }));
else
{
if (index < vertexGroups.Count - 1) vertexGroups.Insert(index + 1, new VertexGroup(value, percent, new int[] { i }));
else vertexGroups.Add(new VertexGroup(value, percent, new int[] { i }));
}
}
}
}
int FindInsertIndex(Vector3 pos, float value)
{
int lower = 0;
int upper = vertexGroups.Count - 1;
while (lower <= upper)
{
int middle = lower + (upper - lower) / 2;
if (vertexGroups[middle].value == value) return middle;
else if (vertexGroups[middle].value < value) upper = middle - 1;
else lower = middle + 1;
}
return lower;
}
void CalculateTangents()
{
if (vertices.Length == 0)
{
tangents = new Vector4[0];
return;
}
tangents = new Vector4[vertices.Length];
Vector3[] tan1 = new Vector3[vertices.Length];
Vector3[] tan2 = new Vector3[vertices.Length];
for (int i = 0; i < subMeshes.Count; i++)
{
for (int j = 0; j < subMeshes[i].triangles.Length; j += 3)
{
int i1 = subMeshes[i].triangles[j];
int i2 = subMeshes[i].triangles[j + 1];
int i3 = subMeshes[i].triangles[j + 2];
float x1 = vertices[i2].x - vertices[i1].x;
float x2 = vertices[i3].x - vertices[i1].x;
float y1 = vertices[i2].y - vertices[i1].y;
float y2 = vertices[i3].y - vertices[i1].y;
float z1 = vertices[i2].z - vertices[i1].z;
float z2 = vertices[i3].z - vertices[i1].z;
float s1 = uv[i2].x - uv[i1].x;
float s2 = uv[i3].x - uv[i1].x;
float t1 = uv[i2].y - uv[i1].y;
float t2 = uv[i3].y - uv[i1].y;
float div = s1 * t2 - s2 * t1;
float r = div == 0f ? 0f : 1f / div;
Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
tan1[i1] += sdir;
tan1[i2] += sdir;
tan1[i3] += sdir;
tan2[i1] += tdir;
tan2[i2] += tdir;
tan2[i3] += tdir;
}
}
for (int i = 0; i < vertices.Length; i++)
{
Vector3 n = normals[i];
Vector3 t = tan1[i];
Vector3.OrthoNormalize(ref n, ref t);
tangents[i].x = t.x;
tangents[i].y = t.y;
tangents[i].z = t.z;
tangents[i].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[i]) < 0.0f) ? -1.0f : 1.0f;
}
}
[System.Serializable]
public class Submesh
{
public int[] triangles = new int[0];
public Submesh()
{
}
public Submesh(int[] input)
{
triangles = new int[input.Length];
input.CopyTo(triangles, 0);
}
}
[System.Serializable]
public class VertexGroup
{
public float value = 0f;
public double percent = 0.0;
public int[] ids;
public VertexGroup(float val, double perc, int[] vertIds)
{
percent = perc;
value = val;
ids = vertIds;
}
public void AddId(int id)
{
int[] newIds = new int[ids.Length + 1];
ids.CopyTo(newIds, 0);
newIds[newIds.Length - 1] = id;
ids = newIds;
}
}
}
}
}
}