From 48349b598dd2b1a61febf5e95324b9ac6d68ed2c Mon Sep 17 00:00:00 2001 From: PopSlime Date: Fri, 14 Apr 2023 14:29:17 +0800 Subject: [PATCH] Separate `PolygonSGO` to individual file. --- Assets/Cryville/Crtr/Components/PolygonSGO.cs | 228 ++++++++++++++++++ .../Crtr/Components/PolygonSGO.cs.meta | 11 + .../Crtr/Components/SectionalGameObject.cs | 225 ----------------- 3 files changed, 239 insertions(+), 225 deletions(-) create mode 100644 Assets/Cryville/Crtr/Components/PolygonSGO.cs create mode 100644 Assets/Cryville/Crtr/Components/PolygonSGO.cs.meta diff --git a/Assets/Cryville/Crtr/Components/PolygonSGO.cs b/Assets/Cryville/Crtr/Components/PolygonSGO.cs new file mode 100644 index 0000000..55cf981 --- /dev/null +++ b/Assets/Cryville/Crtr/Components/PolygonSGO.cs @@ -0,0 +1,228 @@ +using Cryville.Common.Buffers; +using Cryville.Common.Pdt; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Cryville.Crtr.Components { + public class PolygonSGO : SectionalGameObject { + static readonly SimpleObjectPool> _ptPool = new SimpleObjectPool>(1024); + static readonly SimpleObjectPool> _lPool = new SimpleObjectPool>(1024); + + static readonly ListPool _indexPool = new ListPool(); + static readonly ListPool _vertPool = new ListPool(); + static readonly ListPool _uvPool = new ListPool(); + static readonly ArrayPool _shapePool = new ArrayPool(0x100, 0x10000); + + public PolygonSGO() { + SubmitProperty("head", new PropOp.String(v => head.FrameName = v)); + SubmitProperty("body", new PropOp.String(v => body.FrameName = v)); + SubmitProperty("tail", new PropOp.String(v => tail.FrameName = v)); + SubmitProperty("shape", new op_set_shape(this), 2); + } + +#pragma warning disable IDE1006 + public class op_set_shape : PdtOperator { + readonly PolygonSGO _self; + public op_set_shape(PolygonSGO self) : base(1) { + _self = self; + } + protected override unsafe void Execute() { + var o = GetOperand(0); + if (o.Type != PdtInternalType.Vector) throw new ArgumentException("Not a vector"); + _self._shapeLength = (o.Length - sizeof(int)) / sizeof(Vector2); + if (_self._shape != null) _shapePool.Return(_self._shape); + _self._shape = _shapePool.Rent(_self._shapeLength); + for (int i = 0; i < _self._shapeLength; i++) { + _self._shape[i] = o.As(i * sizeof(Vector2)); + } + } + } +#pragma warning restore IDE1006 + + int _shapeLength = 0; + Vector2[] _shape = null; + float GetWidth() { + float r = 0; + for (int i = 1; i < _shapeLength; i++) { + r += (_shape[i] - _shape[i-1]).magnitude; + } + return r; + } + + public SpriteInfo head = new SpriteInfo(); + public SpriteInfo body = new SpriteInfo(); + public SpriteInfo tail = new SpriteInfo(); + + List vertices; + List lengths; + float sumLength = 0; + + public override void Init() { + base.Init(); + mesh.Init(transform); + mesh.Mesh = new Mesh(); + + mesh.Renderer.sharedMaterials = materials = new Material[] { + MeshWrapper.NewMaterial(), + MeshWrapper.NewMaterial(), + MeshWrapper.NewMaterial(), + }; + head.Bind(materials[0]); + body.Bind(materials[1]); + tail.Bind(materials[2]); + + UpdateZIndex(); + } + + protected override void OnDestroy() { + if (_shape != null) _shapePool.Return(_shape); + if (vertices != null) { + _ptPool.Return(vertices); + _lPool.Return(lengths); + } + base.OnDestroy(); + } + + protected override void AppendPointInternal(Vector3 p, Quaternion r) { + if (vertices == null) { + vertices = _ptPool.Rent(); + lengths = _lPool.Rent(); + } + + for (int i = 0; i < _shapeLength; i++) { + Vector2 sp = r * _shape[i]; + vertices.Add(p + (Vector3)sp); + } + + if (prevpt != null) { + float len = (p - prevpt.Value).magnitude; + lengths.Add(len); + sumLength += len; + } + } + + List verts; + List uvs; + List trih = null, trib = null, trit = null; + static readonly List _emptyTris = new List(); + + public override void Seal() { + if (vertCount <= 1 || sumLength == 0) return; + int vcpsec = _shapeLength; // Vertex Count Per Section + float width = GetWidth(); + float headLength = 0; + if (head.Frame != null) headLength = width / head.Ratio; + float tailLength = 0; + if (tail.Frame != null) tailLength = width / tail.Ratio; + float endLength = headLength + tailLength; + if (sumLength <= endLength) { + // The total length of the two ends is longer than the whole mesh, squeeze the two ends + float ratio = sumLength / endLength; + headLength *= ratio; + tailLength *= ratio; + } + + // Find the vertex counts needed for the three parts from the head + float l0 = 0; + int hvc = 0; + for (; l0 < headLength && hvc < lengths.Count; hvc++) + l0 += lengths[hvc]; + int bvc = 0; + for (; l0 < sumLength - tailLength && hvc + bvc < lengths.Count; bvc++) + l0 += lengths[hvc + bvc]; + int tvc = lengths.Count - hvc - bvc + 1; + if (hvc > 0) { + hvc++; + bvc++; + } + bvc++; + int vc = hvc + bvc + tvc; + + verts = _vertPool.Rent(vc * vcpsec); + uvs = _uvPool.Rent(vc * vcpsec); + int i = 0; int t = 0; float l = 0; int m = 0; + if (head.Frame != null) { m++; GenerateMeshTo(verts, uvs, out trih, head, ref i, ref t, ref l, 0, headLength, vcpsec, hvc); } + if (body.Frame != null) { m++; GenerateMeshTo(verts, uvs, out trib, body, ref i, ref t, ref l, headLength, sumLength - tailLength, vcpsec, hvc + bvc); } + if (tail.Frame != null) { m++; GenerateMeshTo(verts, uvs, out trit, tail, ref i, ref t, ref l, sumLength - tailLength, sumLength, vcpsec, vc); } + + mesh.Mesh.subMeshCount = 3; + m = 0; + mesh.Mesh.SetVertices(verts); + mesh.Mesh.SetUVs(0, uvs); + mesh.Mesh.SetTriangles(head.Frame == null ? _emptyTris : trih, m++); + mesh.Mesh.SetTriangles(body.Frame == null ? _emptyTris : trib, m++); + mesh.Mesh.SetTriangles(tail.Frame == null ? _emptyTris : trit, m++); + mesh.Mesh.RecalculateNormals(); + + _vertPool.Return(verts); verts = null; + _uvPool.Return(uvs); uvs = null; + if (trih != null) { _indexPool.Return(trih); trih = null; } + if (trib != null) { _indexPool.Return(trib); trib = null; } + if (trit != null) { _indexPool.Return(trit); trit = null; } + } + + void GenerateMeshTo(List verts, List uvs, out List tris, SpriteInfo info, ref int i, ref int t, ref float l, float startl, float endl, int vcpsec, int vend) { + if (i > lengths.Count) { + tris = _indexPool.Rent(0); + return; + } + + int t0 = t; + var frame = info.Frame; + + if (startl != 0) { + float pl2 = l - lengths[i - 1]; + float fr2 = (startl - pl2) / (l - pl2); + for (int j = 0; j < vcpsec; j++, t++) { + verts[t] = + vertices[vcpsec*(i-1)+j] * (1-fr2) + + vertices[vcpsec*i+j] * fr2; + var u = j / (vcpsec - 1); + if (frame != null) uvs[t] = frame.GetUV(u, 0); + } + } + for (; t / vcpsec < vend - 1; i++) { + var v = (l - startl) / (endl - startl); + for (int j = 0; j < vcpsec; j++, t++) { + verts[t] = vertices[vcpsec*i+j]; + var u = j / (vcpsec - 1); + if (frame != null) uvs[t] = frame.GetUV(u, v); + } + l += lengths[i]; + } + float pl = l - lengths[i - 1]; + float fr = (endl - pl) / (l - pl); + for (int j = 0; j < vcpsec; j++, t++) { + verts[t] = + vertices[vcpsec*(i-1)+j] * (1-fr) + + vertices[vcpsec*i+j] * fr; + var u = j / (vcpsec - 1); + if (frame != null) uvs[t] = frame.GetUV(u, 1); + } + + tris = _indexPool.Rent((vend - t0 / vcpsec - 1) * (vcpsec - 1) * 6); + int i3 = 0; + for (int i1 = t0 + vcpsec + 1; i1 < t; i1++) { + if (i1 % vcpsec == 0) continue; + int i2 = i1 - vcpsec; + tris[i3++] = i1 - 1; + tris[i3++] = i2; + tris[i3++] = i2 - 1; + tris[i3++] = i1 - 1; + tris[i3++] = i1; + tris[i3++] = i2; + } + } + + public override void Reset() { + base.Reset(); + if (mesh.Initialized) mesh.Mesh.Clear(); + if (vertices != null) { + vertices.Clear(); + lengths.Clear(); + } + sumLength = 0; + } + } +} diff --git a/Assets/Cryville/Crtr/Components/PolygonSGO.cs.meta b/Assets/Cryville/Crtr/Components/PolygonSGO.cs.meta new file mode 100644 index 0000000..97bed49 --- /dev/null +++ b/Assets/Cryville/Crtr/Components/PolygonSGO.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed3932875286a2947b9c600ba47f1066 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Cryville/Crtr/Components/SectionalGameObject.cs b/Assets/Cryville/Crtr/Components/SectionalGameObject.cs index 1eeb853..a9b0af8 100644 --- a/Assets/Cryville/Crtr/Components/SectionalGameObject.cs +++ b/Assets/Cryville/Crtr/Components/SectionalGameObject.cs @@ -1,7 +1,3 @@ -using Cryville.Common.Buffers; -using Cryville.Common.Pdt; -using System; -using System.Collections.Generic; using UnityEngine; namespace Cryville.Crtr.Components { @@ -49,225 +45,4 @@ namespace Cryville.Crtr.Components { prevrot = null; } } - - public class PolygonSGO : SectionalGameObject { - static readonly SimpleObjectPool> _ptPool = new SimpleObjectPool>(1024); - static readonly SimpleObjectPool> _lPool = new SimpleObjectPool>(1024); - - static readonly ListPool _indexPool = new ListPool(); - static readonly ListPool _vertPool = new ListPool(); - static readonly ListPool _uvPool = new ListPool(); - static readonly ArrayPool _shapePool = new ArrayPool(0x100, 0x10000); - - public PolygonSGO() { - SubmitProperty("head", new PropOp.String(v => head.FrameName = v)); - SubmitProperty("body", new PropOp.String(v => body.FrameName = v)); - SubmitProperty("tail", new PropOp.String(v => tail.FrameName = v)); - SubmitProperty("shape", new op_set_shape(this), 2); - } - -#pragma warning disable IDE1006 - public class op_set_shape : PdtOperator { - readonly PolygonSGO _self; - public op_set_shape(PolygonSGO self) : base(1) { - _self = self; - } - protected override unsafe void Execute() { - var o = GetOperand(0); - if (o.Type != PdtInternalType.Vector) throw new ArgumentException("Not a vector"); - _self._shapeLength = (o.Length - sizeof(int)) / sizeof(Vector2); - if (_self._shape != null) _shapePool.Return(_self._shape); - _self._shape = _shapePool.Rent(_self._shapeLength); - for (int i = 0; i < _self._shapeLength; i++) { - _self._shape[i] = o.As(i * sizeof(Vector2)); - } - } - } -#pragma warning restore IDE1006 - - int _shapeLength = 0; - Vector2[] _shape = null; - float GetWidth() { - float r = 0; - for (int i = 1; i < _shapeLength; i++) { - r += (_shape[i] - _shape[i-1]).magnitude; - } - return r; - } - - public SpriteInfo head = new SpriteInfo(); - public SpriteInfo body = new SpriteInfo(); - public SpriteInfo tail = new SpriteInfo(); - - List vertices; - List lengths; - float sumLength = 0; - - public override void Init() { - base.Init(); - mesh.Init(transform); - mesh.Mesh = new Mesh(); - - mesh.Renderer.sharedMaterials = materials = new Material[] { - MeshWrapper.NewMaterial(), - MeshWrapper.NewMaterial(), - MeshWrapper.NewMaterial(), - }; - head.Bind(materials[0]); - body.Bind(materials[1]); - tail.Bind(materials[2]); - - UpdateZIndex(); - } - - protected override void OnDestroy() { - if (_shape != null) _shapePool.Return(_shape); - if (vertices != null) { - _ptPool.Return(vertices); - _lPool.Return(lengths); - } - base.OnDestroy(); - } - - protected override void AppendPointInternal(Vector3 p, Quaternion r) { - if (vertices == null) { - vertices = _ptPool.Rent(); - lengths = _lPool.Rent(); - } - - for (int i = 0; i < _shapeLength; i++) { - Vector2 sp = r * _shape[i]; - vertices.Add(p + (Vector3)sp); - } - - if (prevpt != null) { - float len = (p - prevpt.Value).magnitude; - lengths.Add(len); - sumLength += len; - } - } - - List verts; - List uvs; - List trih = null, trib = null, trit = null; - static readonly List _emptyTris = new List(); - - public override void Seal() { - if (vertCount <= 1 || sumLength == 0) return; - int vcpsec = _shapeLength; // Vertex Count Per Section - float width = GetWidth(); - float headLength = 0; - if (head.Frame != null) headLength = width / head.Ratio; - float tailLength = 0; - if (tail.Frame != null) tailLength = width / tail.Ratio; - float endLength = headLength + tailLength; - if (sumLength <= endLength) { - // The total length of the two ends is longer than the whole mesh, squeeze the two ends - float ratio = sumLength / endLength; - headLength *= ratio; - tailLength *= ratio; - } - - // Find the vertex counts needed for the three parts from the head - float l0 = 0; - int hvc = 0; - for (; l0 < headLength && hvc < lengths.Count; hvc++) - l0 += lengths[hvc]; - int bvc = 0; - for (; l0 < sumLength - tailLength && hvc + bvc < lengths.Count; bvc++) - l0 += lengths[hvc + bvc]; - int tvc = lengths.Count - hvc - bvc + 1; - if (hvc > 0) { - hvc++; - bvc++; - } - bvc++; - int vc = hvc + bvc + tvc; - - verts = _vertPool.Rent(vc * vcpsec); - uvs = _uvPool.Rent(vc * vcpsec); - int i = 0; int t = 0; float l = 0; int m = 0; - if (head.Frame != null) { m++; GenerateMeshTo(verts, uvs, out trih, head, ref i, ref t, ref l, 0, headLength, vcpsec, hvc); } - if (body.Frame != null) { m++; GenerateMeshTo(verts, uvs, out trib, body, ref i, ref t, ref l, headLength, sumLength - tailLength, vcpsec, hvc + bvc); } - if (tail.Frame != null) { m++; GenerateMeshTo(verts, uvs, out trit, tail, ref i, ref t, ref l, sumLength - tailLength, sumLength, vcpsec, vc); } - - mesh.Mesh.subMeshCount = 3; - m = 0; - mesh.Mesh.SetVertices(verts); - mesh.Mesh.SetUVs(0, uvs); - mesh.Mesh.SetTriangles(head.Frame == null ? _emptyTris : trih, m++); - mesh.Mesh.SetTriangles(body.Frame == null ? _emptyTris : trib, m++); - mesh.Mesh.SetTriangles(tail.Frame == null ? _emptyTris : trit, m++); - mesh.Mesh.RecalculateNormals(); - - _vertPool.Return(verts); verts = null; - _uvPool.Return(uvs); uvs = null; - if (trih != null) { _indexPool.Return(trih); trih = null; } - if (trib != null) { _indexPool.Return(trib); trib = null; } - if (trit != null) { _indexPool.Return(trit); trit = null; } - } - - void GenerateMeshTo(List verts, List uvs, out List tris, SpriteInfo info, ref int i, ref int t, ref float l, float startl, float endl, int vcpsec, int vend) { - if (i > lengths.Count) { - tris = _indexPool.Rent(0); - return; - } - - int t0 = t; - var frame = info.Frame; - - if (startl != 0) { - float pl2 = l - lengths[i - 1]; - float fr2 = (startl - pl2) / (l - pl2); - for (int j = 0; j < vcpsec; j++, t++) { - verts[t] = - vertices[vcpsec*(i-1)+j] * (1-fr2) - + vertices[vcpsec*i+j] * fr2; - var u = j / (vcpsec - 1); - if (frame != null) uvs[t] = frame.GetUV(u, 0); - } - } - for (; t / vcpsec < vend - 1; i++) { - var v = (l - startl) / (endl - startl); - for (int j = 0; j < vcpsec; j++, t++) { - verts[t] = vertices[vcpsec*i+j]; - var u = j / (vcpsec - 1); - if (frame != null) uvs[t] = frame.GetUV(u, v); - } - l += lengths[i]; - } - float pl = l - lengths[i - 1]; - float fr = (endl - pl) / (l - pl); - for (int j = 0; j < vcpsec; j++, t++) { - verts[t] = - vertices[vcpsec*(i-1)+j] * (1-fr) - + vertices[vcpsec*i+j] * fr; - var u = j / (vcpsec - 1); - if (frame != null) uvs[t] = frame.GetUV(u, 1); - } - - tris = _indexPool.Rent((vend - t0 / vcpsec - 1) * (vcpsec - 1) * 6); - int i3 = 0; - for (int i1 = t0 + vcpsec + 1; i1 < t; i1++) { - if (i1 % vcpsec == 0) continue; - int i2 = i1 - vcpsec; - tris[i3++] = i1 - 1; - tris[i3++] = i2; - tris[i3++] = i2 - 1; - tris[i3++] = i1 - 1; - tris[i3++] = i1; - tris[i3++] = i2; - } - } - - public override void Reset() { - base.Reset(); - if (mesh.Initialized) mesh.Mesh.Clear(); - if (vertices != null) { - vertices.Clear(); - lengths.Clear(); - } - sumLength = 0; - } - } }