将Spline移出Plugin,以调整SplineRenderer的OnWillCameraRender
This commit is contained in:
384
Assets/Dreamteck/Splines/Components/TubeGenerator.cs
Normal file
384
Assets/Dreamteck/Splines/Components/TubeGenerator.cs
Normal file
@@ -0,0 +1,384 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace Dreamteck.Splines
|
||||
{
|
||||
[RequireComponent(typeof(MeshFilter))]
|
||||
[RequireComponent(typeof(MeshRenderer))]
|
||||
[AddComponentMenu("Dreamteck/Splines/Users/Tube Generator")]
|
||||
public class TubeGenerator : MeshGenerator
|
||||
{
|
||||
public enum CapMethod { None, Flat, Round }
|
||||
|
||||
public int sides
|
||||
{
|
||||
get { return _sides; }
|
||||
set
|
||||
{
|
||||
if (value != _sides)
|
||||
{
|
||||
if (value < 3) value = 3;
|
||||
_sides = value;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CapMethod capMode
|
||||
{
|
||||
get { return _capMode; }
|
||||
set
|
||||
{
|
||||
if (value != _capMode)
|
||||
{
|
||||
_capMode = value;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int roundCapLatitude
|
||||
{
|
||||
get { return _roundCapLatitude; }
|
||||
set
|
||||
{
|
||||
if (value < 1) value = 1;
|
||||
if (value != _roundCapLatitude)
|
||||
{
|
||||
_roundCapLatitude = value;
|
||||
if(_capMode == CapMethod.Round) Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float revolve
|
||||
{
|
||||
get { return _revolve; }
|
||||
set
|
||||
{
|
||||
if (value != _revolve)
|
||||
{
|
||||
_revolve = value;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float capUVScale
|
||||
{
|
||||
get { return _capUVScale; }
|
||||
set
|
||||
{
|
||||
if (value != _capUVScale)
|
||||
{
|
||||
_capUVScale = value;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float uvTwist
|
||||
{
|
||||
get { return _uvTwist; }
|
||||
set
|
||||
{
|
||||
if (value != _uvTwist)
|
||||
{
|
||||
_uvTwist = value;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private int _sides = 12;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private int _roundCapLatitude = 6;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private CapMethod _capMode = CapMethod.None;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
[Range(0f, 360f)]
|
||||
private float _revolve = 360f;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private float _capUVScale = 1f;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private float _uvTwist = 0f;
|
||||
|
||||
private bool useCap
|
||||
{
|
||||
get
|
||||
{
|
||||
bool isCapSet = _capMode != CapMethod.None;
|
||||
if (spline != null) return isCapSet && (!spline.isClosed || span < 1f);
|
||||
return isCapSet;
|
||||
}
|
||||
}
|
||||
|
||||
protected override string meshName => "Tube";
|
||||
|
||||
private int bodyVertexCount = 0;
|
||||
private int bodyTrisCount = 0;
|
||||
private int capVertexCount = 0;
|
||||
private int capTrisCount = 0;
|
||||
|
||||
protected override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
}
|
||||
|
||||
protected override void BuildMesh()
|
||||
{
|
||||
if (_sides <= 2) return;
|
||||
base.BuildMesh();
|
||||
bodyVertexCount = (_sides + 1) * sampleCount;
|
||||
CapMethod _capModeFinal = _capMode;
|
||||
if (!useCap)
|
||||
{
|
||||
_capModeFinal = CapMethod.None;
|
||||
}
|
||||
switch (_capModeFinal)
|
||||
{
|
||||
case CapMethod.Flat: capVertexCount = _sides + 1; break;
|
||||
case CapMethod.Round: capVertexCount = _roundCapLatitude * (sides + 1); break;
|
||||
default: capVertexCount = 0; break;
|
||||
}
|
||||
int vertexCount = bodyVertexCount + capVertexCount * 2;
|
||||
|
||||
bodyTrisCount = _sides * (sampleCount - 1) * 2 * 3;
|
||||
switch (_capModeFinal)
|
||||
{
|
||||
case CapMethod.Flat: capTrisCount = (_sides - 1) * 3 * 2; break;
|
||||
case CapMethod.Round: capTrisCount = _sides * _roundCapLatitude * 6; break;
|
||||
default: capTrisCount = 0; break;
|
||||
}
|
||||
AllocateMesh(vertexCount, bodyTrisCount + capTrisCount * 2);
|
||||
|
||||
Generate();
|
||||
switch (_capModeFinal)
|
||||
{
|
||||
case CapMethod.Flat: GenerateFlatCaps(); break;
|
||||
case CapMethod.Round: GenerateRoundCaps(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void Generate()
|
||||
{
|
||||
int vertexIndex = 0;
|
||||
ResetUVDistance();
|
||||
bool hasOffset = offset != Vector3.zero;
|
||||
for (int i = 0; i < sampleCount; i++)
|
||||
{
|
||||
GetSample(i, ref evalResult);
|
||||
Vector3 center = evalResult.position;
|
||||
Vector3 right = evalResult.right;
|
||||
float resultSize = GetBaseSize(evalResult);
|
||||
if (hasOffset)
|
||||
{
|
||||
center += (offset.x * resultSize) * right + (offset.y * resultSize) * evalResult.up + (offset.z * resultSize) * evalResult.forward;
|
||||
}
|
||||
if (uvMode == UVMode.UniformClamp || uvMode == UVMode.UniformClip)
|
||||
{
|
||||
AddUVDistance(i);
|
||||
}
|
||||
Color vertexColor = GetBaseColor(evalResult) * color;
|
||||
for (int n = 0; n < _sides + 1; n++)
|
||||
{
|
||||
float anglePercent = (float)(n) / _sides;
|
||||
Quaternion rot = Quaternion.AngleAxis(_revolve * anglePercent + rotation + 180f, evalResult.forward);
|
||||
_tsMesh.vertices[vertexIndex] = center + rot * right * (size * resultSize * 0.5f);
|
||||
CalculateUVs(evalResult.percent, anglePercent);
|
||||
_tsMesh.uv[vertexIndex] = Vector2.one * 0.5f + (Vector2)(Quaternion.AngleAxis(uvRotation + 180f, Vector3.forward) * (Vector2.one * 0.5f - (__uvs + Vector2.right * ((float)evalResult.percent * _uvTwist))));
|
||||
_tsMesh.normals[vertexIndex] = Vector3.Normalize(_tsMesh.vertices[vertexIndex] - center);
|
||||
_tsMesh.colors[vertexIndex] = vertexColor;
|
||||
vertexIndex++;
|
||||
}
|
||||
}
|
||||
MeshUtility.GeneratePlaneTriangles(ref _tsMesh.triangles, _sides, sampleCount, false);
|
||||
}
|
||||
|
||||
void GenerateFlatCaps()
|
||||
{
|
||||
//Start Cap
|
||||
|
||||
GetSample(0, ref evalResult);
|
||||
for (int i = 0; i < _sides+1; i++)
|
||||
{
|
||||
int index = bodyVertexCount + i;
|
||||
_tsMesh.vertices[index] = _tsMesh.vertices[i];
|
||||
_tsMesh.normals[index] = -evalResult.forward;
|
||||
_tsMesh.colors[index] = _tsMesh.colors[i];
|
||||
_tsMesh.uv[index] = Quaternion.AngleAxis(_revolve * (((float)i) / (_sides - 1)), Vector3.forward) * Vector2.right * (0.5f * capUVScale) + Vector3.right * 0.5f + Vector3.up * 0.5f;
|
||||
}
|
||||
|
||||
//End Cap
|
||||
GetSample(sampleCount - 1, ref evalResult);
|
||||
for (int i = 0; i < _sides + 1; i++)
|
||||
{
|
||||
int index = bodyVertexCount + (_sides + 1) + i;
|
||||
int bodyIndex = bodyVertexCount - (_sides + 1) + i;
|
||||
_tsMesh.vertices[index] = _tsMesh.vertices[bodyIndex];
|
||||
_tsMesh.normals[index] = evalResult.forward;
|
||||
_tsMesh.colors[index] = _tsMesh.colors[bodyIndex];
|
||||
_tsMesh.uv[index] = Quaternion.AngleAxis(_revolve * ((float)(bodyIndex) / (_sides - 1)), Vector3.forward) * Vector2.right * (0.5f * capUVScale) + Vector3.right * 0.5f + Vector3.up * 0.5f;
|
||||
}
|
||||
|
||||
int t = bodyTrisCount;
|
||||
bool fullIntegrity = _revolve == 360f;
|
||||
int finalSides = fullIntegrity ? _sides - 1 : _sides;
|
||||
//Start cap
|
||||
for (int i = 0; i < finalSides - 1; i++)
|
||||
{
|
||||
_tsMesh.triangles[t++] = i + bodyVertexCount + 2;
|
||||
_tsMesh.triangles[t++] = i + +bodyVertexCount + 1;
|
||||
_tsMesh.triangles[t++] = bodyVertexCount;
|
||||
}
|
||||
|
||||
//End cap
|
||||
for (int i = 0; i < finalSides - 1; i++)
|
||||
{
|
||||
_tsMesh.triangles[t++] = bodyVertexCount + (_sides + 1);
|
||||
_tsMesh.triangles[t++] = i + 1 + bodyVertexCount + (_sides + 1);
|
||||
_tsMesh.triangles[t++] = i + 2 + bodyVertexCount + (_sides + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateRoundCaps()
|
||||
{
|
||||
//Start Cap
|
||||
GetSample(0, ref evalResult);
|
||||
Vector3 center = evalResult.position;
|
||||
bool hasOffset = offset != Vector3.zero;
|
||||
float resultSize = GetBaseSize(evalResult);
|
||||
if (hasOffset)
|
||||
{
|
||||
center += (offset.x * resultSize) * evalResult.right + (offset.y * resultSize) * evalResult.up + (offset.z * resultSize) * evalResult.forward;
|
||||
}
|
||||
Quaternion lookRot = Quaternion.LookRotation(-evalResult.forward, evalResult.up);
|
||||
float startV = 0f;
|
||||
float capLengthPercent = 0f;
|
||||
switch (uvMode)
|
||||
{
|
||||
case UVMode.Clip: startV = (float)evalResult.percent;
|
||||
capLengthPercent = (size * 0.5f) / spline.CalculateLength(); break;
|
||||
case UVMode.UniformClip:
|
||||
startV = spline.CalculateLength(0.0, evalResult.percent);
|
||||
capLengthPercent = size * 0.5f; break;
|
||||
case UVMode.UniformClamp:
|
||||
startV = 0f;
|
||||
capLengthPercent = size * 0.5f / (float)span;
|
||||
break;
|
||||
case UVMode.Clamp: capLengthPercent = (size * 0.5f) / spline.CalculateLength(clipFrom, clipTo); break;
|
||||
}
|
||||
|
||||
Color vertexColor = GetBaseColor(evalResult) * color;
|
||||
for (int lat = 1; lat < _roundCapLatitude+1; lat++)
|
||||
{
|
||||
float latitudePercent = ((float)lat / _roundCapLatitude);
|
||||
float latAngle = 90f * latitudePercent;
|
||||
for (int lon = 0; lon <= sides; lon++)
|
||||
{
|
||||
float anglePercent = (float)lon / sides;
|
||||
int index = bodyVertexCount + lon + (lat-1) * (sides + 1);
|
||||
Quaternion rot = Quaternion.AngleAxis(_revolve * anglePercent + rotation + 180f, -Vector3.forward) * Quaternion.AngleAxis(latAngle, Vector3.up);
|
||||
_tsMesh.vertices[index] = center + lookRot * rot * -Vector3.right * (size * 0.5f * evalResult.size);
|
||||
_tsMesh.colors[index] = vertexColor;
|
||||
_tsMesh.normals[index] = (_tsMesh.vertices[index] - center).normalized;
|
||||
float baseV = startV + capLengthPercent * latitudePercent;
|
||||
Vector2 baseUV = new Vector2(anglePercent * uvScale.x - baseV * _uvTwist, baseV * uvScale.y) - uvOffset;
|
||||
_tsMesh.uv[index] = Vector2.one * 0.5f + (Vector2)(Quaternion.AngleAxis(uvRotation + 180f, Vector3.forward) * (Vector2.one * 0.5f - baseUV));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Triangles
|
||||
int t = bodyTrisCount;
|
||||
for (int z = -1; z < _roundCapLatitude - 1; z++)
|
||||
{
|
||||
for (int x = 0; x < sides; x++)
|
||||
{
|
||||
int current = bodyVertexCount + x + z * (sides + 1);
|
||||
int next = current + (sides + 1);
|
||||
if (z == -1)
|
||||
{
|
||||
current = x;
|
||||
next = bodyVertexCount + x;
|
||||
}
|
||||
_tsMesh.triangles[t++] = next + 1;
|
||||
_tsMesh.triangles[t++] = current + 1;
|
||||
_tsMesh.triangles[t++] = current;
|
||||
_tsMesh.triangles[t++] = next;
|
||||
_tsMesh.triangles[t++] = next + 1;
|
||||
_tsMesh.triangles[t++] = current;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//End Cap
|
||||
GetSample(sampleCount - 1, ref evalResult);
|
||||
center = evalResult.position;
|
||||
resultSize = GetBaseSize(evalResult);
|
||||
if (hasOffset)
|
||||
{
|
||||
center += (offset.x * resultSize) * evalResult.right + (offset.y * resultSize) * evalResult.up + (offset.z * resultSize) * evalResult.forward;
|
||||
}
|
||||
lookRot = Quaternion.LookRotation(evalResult.forward, evalResult.up);
|
||||
switch (uvMode)
|
||||
{
|
||||
case UVMode.Clip: startV = (float)evalResult.percent; break;
|
||||
case UVMode.UniformClip: startV = spline.CalculateLength(0.0, evalResult.percent); break;
|
||||
case UVMode.Clamp: startV = 1f; break;
|
||||
case UVMode.UniformClamp: startV = spline.CalculateLength(); break;
|
||||
}
|
||||
|
||||
vertexColor = GetBaseColor(evalResult) * color;
|
||||
for (int lat = 1; lat < _roundCapLatitude+1; lat++)
|
||||
{
|
||||
float latitudePercent = ((float)lat / _roundCapLatitude);
|
||||
float latAngle = 90f * latitudePercent;
|
||||
for (int lon = 0; lon <= sides; lon++)
|
||||
{
|
||||
float anglePercent = (float)lon / sides;
|
||||
int index = bodyVertexCount + capVertexCount + lon + (lat - 1) * (sides + 1);
|
||||
Quaternion rot = Quaternion.AngleAxis(_revolve * anglePercent + rotation + 180f, Vector3.forward) * Quaternion.AngleAxis(latAngle, -Vector3.up);
|
||||
_tsMesh.vertices[index] = center + lookRot * rot * Vector3.right * size * 0.5f * evalResult.size;
|
||||
_tsMesh.normals[index] = (_tsMesh.vertices[index] - center).normalized;
|
||||
_tsMesh.colors[index] = vertexColor;
|
||||
float baseV = startV + capLengthPercent * latitudePercent;
|
||||
Vector2 baseUV = new Vector2(anglePercent * uvScale.x + baseV * _uvTwist, baseV * uvScale.y) - uvOffset;
|
||||
_tsMesh.uv[index] = Vector2.one * 0.5f + (Vector2)(Quaternion.AngleAxis(uvRotation + 180f, Vector3.forward) * (Vector2.one * 0.5f - baseUV));
|
||||
}
|
||||
}
|
||||
|
||||
//Triangles
|
||||
for (int z = -1; z < _roundCapLatitude - 1; z++)
|
||||
{
|
||||
for (int x = 0; x < sides; x++)
|
||||
{
|
||||
int current = bodyVertexCount + capVertexCount + x + z * (sides + 1);
|
||||
int next = current + (sides + 1);
|
||||
if (z == -1)
|
||||
{
|
||||
current = bodyVertexCount - (_sides+1) + x;
|
||||
next = bodyVertexCount + capVertexCount + x;
|
||||
}
|
||||
|
||||
_tsMesh.triangles[t++] = current+1;
|
||||
_tsMesh.triangles[t++] = next + 1;
|
||||
_tsMesh.triangles[t++] = next;
|
||||
_tsMesh.triangles[t++] = next;
|
||||
_tsMesh.triangles[t++] = current;
|
||||
_tsMesh.triangles[t++] = current + 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user