diff --git a/Packages/jp.keijiro.metamesh/Editor/Circle.cs b/Packages/jp.keijiro.metamesh/Editor/Circle.cs new file mode 100644 index 0000000..40263d0 --- /dev/null +++ b/Packages/jp.keijiro.metamesh/Editor/Circle.cs @@ -0,0 +1,93 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine.Rendering; +using UnityEngine; +using Unity.Mathematics; + +namespace Metamesh { + +[System.Serializable] +public sealed class Ring +{ + public float Radius = 1; + public float Width = 0.1f; + [Range(0, 1)] public float Angle = 1; + public uint Segments = 32; + public Axis Axis = Axis.Z; + public bool DoubleSided = false; + + public void Generate(Mesh mesh) + { + // Parameter sanitization + var ext = math.min(Radius, Width / 2); + + // Axis selection + var X = float3.zero; + var Y = float3.zero; + var ai = (int)Axis; + X[(ai + 1) % 3] = 1; + Y[(ai + 2) % 3] = 1; + + // Vertex array + var vtx = new List(); + var uv0 = new List(); + + var i_div_o = (Radius - Width / 2) / (Radius + Width / 2); + + for (var i = 0; i < Segments; i++) + { + var phi = 2 * math.PI * Angle * ((float)i / (Segments - 1) - 0.5f); + var (x, y) = (math.cos(phi), math.sin(phi)); + + var v = x * X + y * Y; + vtx.Add(v * (Radius - ext)); + vtx.Add(v * (Radius + ext)); + uv0.Add(math.float2(-x, y) / 2 * i_div_o + 0.5f); + uv0.Add(math.float2(-x, y) / 2 + 0.5f); + } + + if (DoubleSided) + { + vtx = vtx.Concat(vtx).ToList(); + uv0 = uv0.Concat(uv0).ToList(); + } + + // Index array + var idx = new List(); + var n = (int)Segments; + + for (var i = 0; i < n - 1; i++) + { + idx.Add(i * 2); + idx.Add(i * 2 + 1); + idx.Add(i * 2 + 2); + + idx.Add(i * 2 + 1); + idx.Add(i * 2 + 3); + idx.Add(i * 2 + 2); + } + + if (DoubleSided) + { + for (var i = 0; i < n - 1; i++) + { + idx.Add((n + i) * 2); + idx.Add((n + i) * 2 + 2); + idx.Add((n + i) * 2 + 1); + + idx.Add((n + i) * 2 + 1); + idx.Add((n + i) * 2 + 2); + idx.Add((n + i) * 2 + 3); + } + } + + // Mesh object construction + if (vtx.Count > 65535) mesh.indexFormat = IndexFormat.UInt32; + mesh.SetVertices(vtx.Select(v => (Vector3)v).ToList()); + mesh.SetUVs(0, uv0.Select(v => (Vector2)v).ToList()); + mesh.SetIndices(idx, MeshTopology.Triangles, 0); + mesh.RecalculateNormals(); + } +} + +} // namespace Metamesh diff --git a/Packages/jp.keijiro.metamesh/Editor/Circle.cs.meta b/Packages/jp.keijiro.metamesh/Editor/Circle.cs.meta new file mode 100644 index 0000000..764a1da --- /dev/null +++ b/Packages/jp.keijiro.metamesh/Editor/Circle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7702a2af274677f46831fcc54c181843 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/jp.keijiro.metamesh/Editor/Disc.cs b/Packages/jp.keijiro.metamesh/Editor/Disc.cs new file mode 100644 index 0000000..32e973f --- /dev/null +++ b/Packages/jp.keijiro.metamesh/Editor/Disc.cs @@ -0,0 +1,79 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine.Rendering; +using UnityEngine; +using Unity.Mathematics; + +namespace Metamesh { + +[System.Serializable] +public sealed class Disc +{ + public float Radius = 1; + [Range(0, 1)] public float Angle = 1; + public uint Segments = 32; + public Axis Axis = Axis.Z; + public bool DoubleSided = false; + + public void Generate(Mesh mesh) + { + // Axis selection + var X = float3.zero; + var Y = float3.zero; + var ai = (int)Axis; + X[(ai + 1) % 3] = 1; + Y[(ai + 2) % 3] = 1; + + // Vertex array + var vtx = new List(); + var uv0 = new List(); + + for (var i = 0; i < Segments; i++) + { + var phi = 2 * math.PI * Angle * ((float)i / (Segments - 1) - 0.5f); + var (x, y) = (math.cos(phi), math.sin(phi)); + + vtx.Add((x * X + y * Y) * Radius); + uv0.Add(math.float2(-x, y) / 2 + 0.5f); + } + + vtx.Add(0); + uv0.Add(0.5f); + + if (DoubleSided) + { + vtx = vtx.Concat(vtx).ToList(); + uv0 = uv0.Concat(uv0).ToList(); + } + + // Index array + var idx = new List(); + var n = (int)Segments; + + for (var i = 0; i < n - 1; i++) + { + idx.Add(n); + idx.Add(i); + idx.Add(i + 1); + } + + if (DoubleSided) + { + for (var i = 0; i < n - 1; i++) + { + idx.Add(n + 1 + n); + idx.Add(n + 1 + i + 1); + idx.Add(n + 1 + i); + } + } + + // Mesh object construction + if (vtx.Count > 65535) mesh.indexFormat = IndexFormat.UInt32; + mesh.SetVertices(vtx.Select(v => (Vector3)v).ToList()); + mesh.SetUVs(0, uv0.Select(v => (Vector2)v).ToList()); + mesh.SetIndices(idx, MeshTopology.Triangles, 0); + mesh.RecalculateNormals(); + } +} + +} // namespace Metamesh diff --git a/Packages/jp.keijiro.metamesh/Editor/Disc.cs.meta b/Packages/jp.keijiro.metamesh/Editor/Disc.cs.meta new file mode 100644 index 0000000..1a89eeb --- /dev/null +++ b/Packages/jp.keijiro.metamesh/Editor/Disc.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 032b0788d3b23244b9b8376b84c0de8f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/jp.keijiro.metamesh/Editor/Enums.cs b/Packages/jp.keijiro.metamesh/Editor/Enums.cs index d9697e5..60fd46a 100644 --- a/Packages/jp.keijiro.metamesh/Editor/Enums.cs +++ b/Packages/jp.keijiro.metamesh/Editor/Enums.cs @@ -1,6 +1,6 @@ namespace Metamesh { -public enum Shape { Plane, Box, Sphere, Icosphere, Cylinder, RoundedBox } +public enum Shape { Plane, Box, Sphere, Icosphere, Cylinder, RoundedBox, Ring, Disc } public enum Axis { X, Y, Z } } // namespace Metamesh diff --git a/Packages/jp.keijiro.metamesh/Editor/MetameshImporter.cs b/Packages/jp.keijiro.metamesh/Editor/MetameshImporter.cs index ac60bf9..f2fd925 100644 --- a/Packages/jp.keijiro.metamesh/Editor/MetameshImporter.cs +++ b/Packages/jp.keijiro.metamesh/Editor/MetameshImporter.cs @@ -20,6 +20,8 @@ public sealed class MetameshImporter : ScriptedImporter [SerializeField] Icosphere _icosphere = new Icosphere(); [SerializeField] Cylinder _cylinder = new Cylinder(); [SerializeField] RoundedBox _roundedBox = new RoundedBox(); + [SerializeField] Ring _ring = new Ring(); + [SerializeField] Disc _disc = new Disc(); public override void OnImportAsset(AssetImportContext context) { @@ -56,6 +58,8 @@ Mesh ImportAsMesh(string path) case Shape.Icosphere : _icosphere .Generate(mesh); break; case Shape.Cylinder : _cylinder .Generate(mesh); break; case Shape.RoundedBox : _roundedBox.Generate(mesh); break; + case Shape.Ring : _ring .Generate(mesh); break; + case Shape.Disc : _disc .Generate(mesh); break; } mesh.RecalculateBounds(); diff --git a/Packages/jp.keijiro.metamesh/Editor/MetameshImporterEditor.cs b/Packages/jp.keijiro.metamesh/Editor/MetameshImporterEditor.cs index b6bb93a..6510f1e 100644 --- a/Packages/jp.keijiro.metamesh/Editor/MetameshImporterEditor.cs +++ b/Packages/jp.keijiro.metamesh/Editor/MetameshImporterEditor.cs @@ -18,6 +18,8 @@ sealed class MetameshImporterEditor : ScriptedImporterEditor SerializedProperty _icosphere; SerializedProperty _cylinder; SerializedProperty _roundedBox; + SerializedProperty _ring; + SerializedProperty _disc; public override void OnEnable() { @@ -29,6 +31,8 @@ public override void OnEnable() _icosphere = serializedObject.FindProperty("_icosphere"); _cylinder = serializedObject.FindProperty("_cylinder"); _roundedBox = serializedObject.FindProperty("_roundedBox"); + _ring = serializedObject.FindProperty("_ring"); + _disc = serializedObject.FindProperty("_disc"); } public override void OnInspectorGUI() @@ -45,6 +49,8 @@ public override void OnInspectorGUI() case Shape.Icosphere : EditorGUILayout.PropertyField(_icosphere); break; case Shape.Cylinder : EditorGUILayout.PropertyField(_cylinder); break; case Shape.RoundedBox: EditorGUILayout.PropertyField(_roundedBox); break; + case Shape.Ring : EditorGUILayout.PropertyField(_ring); break; + case Shape.Disc : EditorGUILayout.PropertyField(_disc); break; } serializedObject.ApplyModifiedProperties();