using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace UltraCombos { public class Utilities { const float TWO_PI = Mathf.PI * 2.0f; public static float[] GetShuffleSeeds(int num) { List sources = new List(); for (uint i = 0; i < num; i++) sources.Add((float)i / num); var rnd = new System.Random(); return sources.OrderBy(item => rnd.Next()).ToArray(); } public static Mesh[] GetUVIndexPolygons(int maxParticles, int side, float radius, float randomRadius = 0.0f, float startAngle = 0) { #if UNITY_2017_3_OR_NEWER int num_meshes = 1; #else int limit = 65000; int num_vertices = maxParticles * side; int num_meshes = (num_vertices + limit - 1) / limit; #endif int ptc_per_mesh = maxParticles / num_meshes; Mesh[] meshes = new Mesh[num_meshes]; float r_mul = Mathf.Clamp01(randomRadius); float r_max = radius * (1.0f + r_mul); float r_min = radius * (1.0f - r_mul); for (int i = 0; i < num_meshes; i++) { var vertices = new List(); var uvs = new List(); var normals = new List(); var indices = new List(); for (int j = 0; j < ptc_per_mesh; j++) { int index = i * ptc_per_mesh + j; float delta_a = TWO_PI / side; for (uint k = 0; k < side; k++) { float a = delta_a * k + Mathf.PI / 4; float x = Mathf.Cos(a); float y = Mathf.Sin(a); float r = Random.Range(r_min, r_max); vertices.Add(new Vector3(x * r, y * r, 0)); uvs.Add(new Vector4(x * 0.5f + 0.5f, y * 0.5f + 0.5f, index, k)); normals.Add(new Vector3(0, 0, 1)); } for (int k = 0; k < side - 2; k++) { indices.Add(j * side + 0); indices.Add(j * side + k + 1); indices.Add(j * side + k + 2); } } meshes[i] = new Mesh(); #if UNITY_2017_3_OR_NEWER meshes[i].indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; #endif meshes[i].SetVertices(vertices); meshes[i].SetUVs(0, uvs); meshes[i].SetNormals(normals); meshes[i].SetIndices(indices.ToArray(), MeshTopology.Triangles, 0); meshes[i].bounds = new Bounds(Vector3.zero, Vector3.one * 100.0f); } return meshes; } public static float GetTimeValue() { uint interval = 100000; uint milli_time = (uint)(Time.time * 1000); float value = milli_time % interval / (float)interval; return Mathf.Sin(value * TWO_PI) * 0.5f + 0.5f; // continuous sin value } public static void Release(ref ComputeBuffer buffer) { if (buffer != null) buffer.Release(); buffer = null; } static List skip_camera_names = null; public static bool SkipCamera(string name) { if (skip_camera_names == null) skip_camera_names = new List() { "Preview Camera", "Preview Scene Camera" }; return skip_camera_names.Contains(name); } public static IEnumerator GetRandomParticleData(int amount, List result) { List seeds = new List(); seeds.AddRange(GetShuffleSeeds(amount)); List factors = new List(); factors.AddRange(GetShuffleSeeds(amount)); float radius = 2.0f; const int mod = 1 << 13; for (int i = 0; i < amount; i++) { float x = Random.Range(-1.0f, 1.0f); float y = Random.Range(-1.0f, 1.0f); float z = Random.Range(-1.0f, 1.0f); float r = Mathf.Pow(Random.Range(0.0f, 1.0f), 1.0f / 2.2f) * radius; Vector3 pos = (new Vector3(x, y, z)).normalized * r; Particle p = new Particle(); p.position = pos; p.seed = seeds[i]; p.color = new Vector4(1, 1, 1, factors[i]); p.velocity = Vector3.zero; p.life = Random.Range(1.0f, 0.0f); var q = Random.rotation; p.quat = new Vector4(q.x, q.y, q.z, q.w); p.model_matrix = Matrix4x4.identity; result.Add(p); if (i % mod == 0) { yield return null; } } } public static IEnumerator GetReferencesParticleMesh(List referenceMeshes, int maxParticles, Mesh result) { int totalVertexCount = 0; foreach (var m in referenceMeshes) totalVertexCount += m.vertexCount; int max_particles = maxParticles / referenceMeshes.Count; int num_meshes = 1; int ptc_per_mesh = max_particles / num_meshes; //for (int i = 0; i < num_meshes; i++) { int i = 0; var vertices = new List(); var normals = new List(); var colors = new List(); var uvs = new List(); var indices = new List(); var custom_uvs = new List(); int begin_index = 0; for (int j = 0; j < ptc_per_mesh; j++) { for (int k = 0; k < referenceMeshes.Count; k++) { int index = (i * ptc_per_mesh + j) * referenceMeshes.Count + k; var mesh = referenceMeshes[k]; vertices.AddRange(mesh.vertices); normals.AddRange(mesh.normals); uvs.AddRange(mesh.uv); if (mesh.colors.Length == mesh.vertices.Length) { colors.AddRange(mesh.colors); } else { for (int ci = 0; ci < mesh.vertices.Length; ci++) colors.Add(Color.white); } foreach (var idx in mesh.GetIndices(0)) indices.Add(begin_index + idx); for (int l = 0; l < mesh.vertexCount; l++) custom_uvs.Add(new Vector4(mesh.uv[l].x, mesh.uv[l].y, index, k)); begin_index += mesh.vertexCount; } if (j % 1024 == 0) { yield return null; } } //Mesh m = new Mesh(); if (vertices.Count > 65000) result.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; result.SetVertices(vertices); result.SetNormals(normals); if (colors.Count == vertices.Count) { result.SetColors(colors); } //result.SetUVs(0, uvs); result.SetUVs(0, custom_uvs); result.SetIndices(indices.ToArray(), referenceMeshes[0].GetTopology(0), 0); result.bounds = new Bounds(Vector3.zero, Vector3.one * 100); result.UploadMeshData(false); //meshes.Add(m); } yield return null; } } }