将Spline移出Plugin,以调整SplineRenderer的OnWillCameraRender
This commit is contained in:
344
Assets/Dreamteck/Splines/Components/ComplexSurfaceGenerator.cs
Normal file
344
Assets/Dreamteck/Splines/Components/ComplexSurfaceGenerator.cs
Normal file
@@ -0,0 +1,344 @@
|
||||
namespace Dreamteck.Splines
|
||||
{
|
||||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(MeshFilter))]
|
||||
[RequireComponent(typeof(MeshRenderer))]
|
||||
[AddComponentMenu("Dreamteck/Splines/Complex Surface Generator")]
|
||||
public class ComplexSurfaceGenerator : MeshGenerator
|
||||
{
|
||||
public enum UVWrapMode { Clamp, UniformX, UniformY, Uniform }
|
||||
public enum SubdivisionMode { CatmullRom, BSpline, Linear }
|
||||
public UVWrapMode uvWrapMode
|
||||
{
|
||||
get { return _uvWrapMode; }
|
||||
set
|
||||
{
|
||||
if (value != _uvWrapMode)
|
||||
{
|
||||
_uvWrapMode = value;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int subdivisions
|
||||
{
|
||||
get { return _subdivisions; }
|
||||
set
|
||||
{
|
||||
if (value != _subdivisions)
|
||||
{
|
||||
_subdivisions = value;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SubdivisionMode subdivisionMode
|
||||
{
|
||||
get { return _subdivisionMode; }
|
||||
set
|
||||
{
|
||||
if (value != _subdivisionMode)
|
||||
{
|
||||
_subdivisionMode = value;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool automaticNormals
|
||||
{
|
||||
get { return _automaticNormals; }
|
||||
set
|
||||
{
|
||||
if (value != _automaticNormals)
|
||||
{
|
||||
_automaticNormals = value;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool separateMaterialIDs
|
||||
{
|
||||
get { return _separateMaterialIDs; }
|
||||
set
|
||||
{
|
||||
if (value != _separateMaterialIDs)
|
||||
{
|
||||
_separateMaterialIDs = value;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public SplineComputer[] otherComputers
|
||||
{
|
||||
get { return _otherComputers; }
|
||||
set
|
||||
{
|
||||
bool rebuild = false;
|
||||
if (value.Length != _otherComputers.Length)
|
||||
{
|
||||
rebuild = true;
|
||||
for (int i = 0; i < _otherComputers.Length; i++)
|
||||
{
|
||||
if (_otherComputers[i] != null)
|
||||
{
|
||||
_otherComputers[i].Unsubscribe(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
if (_otherComputers[i] != null)
|
||||
{
|
||||
_otherComputers[i].Unsubscribe(this);
|
||||
}
|
||||
if (value[i] != _otherComputers[i])
|
||||
{
|
||||
rebuild = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rebuild)
|
||||
{
|
||||
_otherComputers = value;
|
||||
for (int i = 0; i < _otherComputers.Length; i++)
|
||||
{
|
||||
if (_otherComputers[i] != null)
|
||||
{
|
||||
if (_otherComputers[i].subscriberCount == 0)
|
||||
{
|
||||
_otherComputers[i].name = "Surface Spline " + (i + 1);
|
||||
}
|
||||
_otherComputers[i].Subscribe(this);
|
||||
}
|
||||
}
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private UVWrapMode _uvWrapMode = UVWrapMode.Clamp;
|
||||
[SerializeField, HideInInspector, Min(1)]
|
||||
private int _subdivisions = 3;
|
||||
[SerializeField, HideInInspector]
|
||||
private SubdivisionMode _subdivisionMode;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private bool _automaticNormals = true;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private bool _separateMaterialIDs = false;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private SplineComputer[] _otherComputers = new SplineComputer[0];
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private Spline[] _splines = new Spline[0];
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private bool _initializedInEditor = false;
|
||||
|
||||
private int iterations => _subdivisions * _otherComputers.Length;
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
_mesh.name = "multispline_surface";
|
||||
for (int i = 0; i < _otherComputers.Length; i++)
|
||||
{
|
||||
_otherComputers[i].onRebuild -= OnOtherRebuild;
|
||||
_otherComputers[i].onRebuild += OnOtherRebuild;
|
||||
}
|
||||
}
|
||||
|
||||
void OnOtherRebuild()
|
||||
{
|
||||
RebuildImmediate();
|
||||
}
|
||||
|
||||
protected override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
}
|
||||
|
||||
private Spline.Type ModeToSplineType(SubdivisionMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case SubdivisionMode.BSpline: return Spline.Type.BSpline;
|
||||
case SubdivisionMode.Linear: return Spline.Type.Linear;
|
||||
default: return Spline.Type.CatmullRom;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void BuildMesh()
|
||||
{
|
||||
if (sampleCount == 0 || _otherComputers.Length == 0)
|
||||
{
|
||||
AllocateMesh(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_splines.Length != sampleCount)
|
||||
{
|
||||
_splines = new Spline[sampleCount];
|
||||
for (int i = 0; i < _splines.Length; i++)
|
||||
{
|
||||
_splines[i] = new Spline(ModeToSplineType(_subdivisionMode));
|
||||
}
|
||||
} else
|
||||
{
|
||||
for (int i = 0; i < _splines.Length; i++)
|
||||
{
|
||||
_splines[i].type = ModeToSplineType(_subdivisionMode);
|
||||
}
|
||||
}
|
||||
|
||||
base.BuildMesh();
|
||||
AllocateMesh(sampleCount * (iterations + 1), iterations * (sampleCount-1) * 6);
|
||||
_tsMesh.triangles = MeshUtility.GeneratePlaneTriangles(sampleCount - 1, iterations + 1, false);
|
||||
GenerateVertices();
|
||||
_tsMesh.subMeshes.Clear();
|
||||
|
||||
if (_separateMaterialIDs)
|
||||
{
|
||||
for (int i = 0; i < _otherComputers.Length; i++)
|
||||
{
|
||||
int[] newTris = MeshUtility.GeneratePlaneTriangles(sampleCount - 1, subdivisions + 1, false);
|
||||
_tsMesh.subMeshes.Add(newTris);
|
||||
for (int n = 0; n < _tsMesh.subMeshes[i].Length; n++)
|
||||
{
|
||||
_tsMesh.subMeshes[i][n] += i * (_subdivisions * sampleCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GenerateVertices()
|
||||
{
|
||||
if (_otherComputers.Length == 0) return;
|
||||
|
||||
ResetUVDistance();
|
||||
|
||||
SplineSample sample = default;
|
||||
SplineSample sample2 = default;
|
||||
|
||||
for (int i = 0; i < _otherComputers.Length + 1; i++)
|
||||
{
|
||||
SplineComputer splineComp = spline;
|
||||
if (i > 0)
|
||||
{
|
||||
splineComp = _otherComputers[i - 1];
|
||||
}
|
||||
|
||||
for (int j = 0; j < sampleCount; j++)
|
||||
{
|
||||
if (_splines[j].points.Length != _otherComputers.Length + 1)
|
||||
{
|
||||
_splines[j].points = new SplinePoint[_otherComputers.Length + 1];
|
||||
}
|
||||
|
||||
double xPercent = DMath.Lerp(clipFrom, clipTo, (double)j / (sampleCount - 1));
|
||||
if (i > 0)
|
||||
{
|
||||
splineComp.Evaluate(xPercent, ref sample);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetSample(j, ref sample);
|
||||
}
|
||||
|
||||
_splines[j].points[i].position = sample.position;
|
||||
_splines[j].points[i].normal = sample.up;
|
||||
_splines[j].points[i].color = sample.color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (int x = 0; x < _splines.Length; x++)
|
||||
{
|
||||
if (uvMode == UVMode.UniformClamp || uvMode == UVMode.UniformClip)
|
||||
{
|
||||
AddUVDistance(x);
|
||||
} else
|
||||
{
|
||||
GetSample(x, ref sample2);
|
||||
}
|
||||
Vector3 lastPos = sample.position;
|
||||
float ydist = 0f;
|
||||
float xPercent = Mathf.Lerp((float)clipFrom, (float)clipTo, (float)x / (_splines.Length - 1));
|
||||
for (int y = 0; y < iterations + 1; y++)
|
||||
{
|
||||
float yPercent = (float)y / iterations;
|
||||
int index = x + y * _splines.Length;
|
||||
_splines[x].Evaluate(yPercent, ref sample);
|
||||
if (y > 0)
|
||||
{
|
||||
ydist += Vector3.Distance(lastPos, sample.position);
|
||||
}
|
||||
lastPos = sample.position;
|
||||
if (uvMode == UVMode.UniformClamp )
|
||||
{
|
||||
__uvs.x = CalculateUVUniformClamp(_vDist);
|
||||
__uvs.y = CalculateUVUniformClamp(ydist);
|
||||
} else if(uvMode == UVMode.UniformClip)
|
||||
{
|
||||
__uvs.x = CalculateUVUniformClip(_vDist);
|
||||
__uvs.y = CalculateUVUniformClip(ydist);
|
||||
}
|
||||
else
|
||||
{
|
||||
CalculateUVs(xPercent, yPercent);
|
||||
}
|
||||
|
||||
_tsMesh.vertices[index] = sample.position;
|
||||
_tsMesh.normals[index] = sample.up;
|
||||
_tsMesh.colors[index] = sample.color;
|
||||
_tsMesh.uv[index] = Vector2.one * 0.5f + (Vector2)(Quaternion.AngleAxis(uvRotation + 180f, Vector3.forward) * (Vector2.one * 0.5f - __uvs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void WriteMesh()
|
||||
{
|
||||
base.WriteMesh();
|
||||
if (_automaticNormals)
|
||||
{
|
||||
_mesh.RecalculateNormals();
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawSpline(Spline spline, Color color, double from = 0.0, double to = 1.0)
|
||||
{
|
||||
double add = spline.moveStep;
|
||||
int iterations = spline.iterations;
|
||||
if (iterations <= 0) return;
|
||||
|
||||
Vector3 prevPoint = spline.EvaluatePosition(from);
|
||||
for (int i = 1; i < iterations; i++)
|
||||
{
|
||||
double p = DMath.Lerp(from, to, (double)i / (iterations - 1));
|
||||
Debug.DrawLine(prevPoint, spline.EvaluatePosition(p), color, 1f);
|
||||
prevPoint = spline.EvaluatePosition(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user