Skip to content
Snippets Groups Projects
Select Git revision
  • 927f3451fc1c0dd8847d5d503a876bbb964f70f6
  • master default
  • JS-based-scroll-rendering
  • Paul_Marius_Level
  • Paul_Marius_2
  • Paul_Marius
  • Andi_Mark
  • be-UnityWebView
  • gitignoreFrameitServer
  • ZimmerBSc
  • Bugfix_StageLoading
  • stages
  • MAZIFAU_Experimental
  • tsc/coneworld
  • tsc/fact-interaction
  • marcel
  • MaZiFAU_TopSort
  • mergeHelper
  • zwischenSpeichern
  • tempAndrToMaster
  • SebBranch
  • 3.0
  • v2.1
  • v2.0
  • v1.0
25 results

IngameUI_OnOffButton_mobile.cs

Blame
  • ShapeGenerator.cs 7.17 KiB
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Unity.Mathematics;
    using UnityEngine;
    
    public abstract class ShapeGenerator : MonoBehaviour
    {
        #region InspectorVariables
        [Header("Parts")]
        public List<MeshFilter> Meshs;
        public List<float> NormalOffset;
        public bool AlternateNormals = false;
        #endregion InspectorVariables
    
        #region UnityMethods
        void Awake() => GenerateShapeForAll();
    
    #if UNITY_EDITOR
        void OnValidate()
        {
            // prevent 'SendMessage cannot be called during Awake, CheckConsistency, or OnValidate' warning
            UnityEditor.EditorApplication.delayCall += GenerateShapeForAll;
        }
    #endif
        #endregion UnityMethods
    
        protected void GenerateShapeForAll()
        {
            float[] _NormalOffset = new float[Meshs.Count];
            NormalOffset?.CopyTo(0, _NormalOffset, 0
                , math.min(NormalOffset.Count, Meshs.Count));
    
            (Vector3[] vertices, int[] triangles) topology =
                GenerateTopology();
    
            if (topology.vertices.Length == 0)
                return;
    
            for (int i = 0; i < Meshs.Count; i++)
            {
                MeshFilter filter = Meshs[i];
                if (filter == null)
                    continue;
    
                Mesh mesh = CreateMesh(topology);
                Vector3[] normals = AlternateNormals
                    ? GetUnweightedNormals(mesh)
                    : mesh.normals;
    
                mesh.SetVertices(
                    mesh.vertices
                    .Zip(normals, (v, n)
                        => v + n * _NormalOffset[i])
                    .ToList()
                );
    
                if (filter.sharedMesh != null)
                    filter.sharedMesh.Clear();
                filter.sharedMesh = mesh;
    
                if (filter.transform.TryGetComponent(out MeshCollider meshCol))
                    meshCol.sharedMesh = filter.sharedMesh;
            }
        }
    
        protected abstract (Vector3[] vertices, int[] triangles) GenerateTopology();
    
        #region Helper
        protected static Mesh CreateMesh((Vector3[] vertices, int[] triangles) meshValues)
        {
            Mesh mesh = new()
            {
                vertices = meshValues.vertices,
                triangles = meshValues.triangles
            };
            mesh.Optimize();
            mesh.RecalculateNormals(); //fix lighting
            return mesh;
        }
    
        protected static Vector3[] GetCirclePoints(float circleRadius, int pointCount)
            => GetCirclePoints(circleRadius, pointCount, Vector3.zero);
    
        protected static Vector3[] GetCirclePoints(float circleRadius, int pointCount, Vector3 offset)
        {
            Vector3[] circle = new Vector3[pointCount];
            float slice = (2f * Mathf.PI) / pointCount;
            for (int i = 0; i < pointCount; i++)
            {
                float rad_angle = i * slice;
                circle[i] =
                    new Vector3(
                        circleRadius * Mathf.Sin(rad_angle),
                        0,
                        circleRadius * Mathf.Cos(rad_angle)
                    ) + offset;
            }
            return circle;
        }
    
        /// <summary>
        /// Creates triangles for a set of vertecies of a flat, convex shape
        /// </summary>
        /// <param name="points"></param>
        /// <param name="invert"></param>
        /// <returns></returns>
        protected static (Vector3[] vertices, int[] triangles) CreatePlane(Vector3[] vertices, bool invert = false)
        {
            if (vertices.Length < 3)
                return (vertices, new int[0]);
    
            int[] triangles = new int[(vertices.Length - 2) * 3];
            for (int i = 1; i < vertices.Length - 1; i++)
            {
                triangles[(i - 1) * 3 + 0] = 0;
                triangles[(i - 1) * 3 + 1] = i;
                triangles[(i - 1) * 3 + 2] = (i + 1);
            }
    
            return (vertices, invert ? triangles.Reverse().ToArray() : triangles);
        }
    
        protected static (Vector3[] vertices, int[] triangles) CreatePrism(
            (Vector3[] vertices, int[] triangles) top,
            (Vector3[] vertices, int[] triangles) bottom,
            int[] boundary_top,
            int[] boundary_bottom
        )
        {
            boundary_top ??= Enumerable.Range(0, top.vertices.Length).ToArray();
            boundary_bottom ??= Enumerable.Range(0, bottom.vertices.Length).ToArray();
    
            if (boundary_top.Length != boundary_bottom.Length
             && !(boundary_top.Length == 1 ^ boundary_bottom.Length == 1))
                Debug.LogWarning("Arguments of different Size; Resulting mesh may be weird!");
            int max = math.max(boundary_top.Length, boundary_bottom.Length);
            int tri_sum = top.triangles.Length + bottom.triangles.Length;
    
            Vector3[] new_vertices = top.vertices.ShallowCloneAppend(bottom.vertices);
    
            int[] new_triangles = new int[tri_sum + 2 * max * 3];
            top.triangles.CopyTo(new_triangles, 0);
            bottom.triangles
                .Select(i => i + top.vertices.Length)
                .ToArray()
                .CopyTo(new_triangles, top.triangles.Length);
    
            for (int i = 0; i < max; i++)
            {
                if (boundary_top.Length > 1)
                {
                    new_triangles[tri_sum + i * 6 + 0] = boundary_top[(i + 1) % boundary_top.Length];
                    new_triangles[tri_sum + i * 6 + 1] = boundary_top[i % boundary_top.Length];
                    new_triangles[tri_sum + i * 6 + 2] =
                        top.vertices.Length + boundary_bottom[i % boundary_bottom.Length];
                }
                if (boundary_bottom.Length > 1)
                {
                    new_triangles[tri_sum + i * 6 + 3] =
                        top.vertices.Length + boundary_bottom[i % boundary_bottom.Length];
                    new_triangles[tri_sum + i * 6 + 4] =
                        top.vertices.Length + boundary_bottom[(i + 1) % boundary_bottom.Length];
                    new_triangles[tri_sum + i * 6 + 5] = boundary_top[(i + 1) % boundary_top.Length];
                }
            }
    
            return (new_vertices, new_triangles);
        }
    
        // Artefacts appear when mesh is unbalanced (e.g. many edges at one vert)
        public static Vector3[] GetUnweightedNormals(Mesh mesh)
        {
            int[] triangles = mesh.triangles;
            Vector3[] verts = mesh.vertices;
    
            Vector3[] normals = new Vector3[mesh.vertexCount];
            int[] weightsum = new int[mesh.vertexCount];
    
            HashSet<int>[] deltas = new HashSet<int>[mesh.vertexCount];
            for (int i = 0; i < deltas.Length; i++)
                deltas[i] = new();
    
            for (int i = 0; i < triangles.Length; i += 3)
            {
                AddEdge(triangles[i + 0], triangles[i + 1]);
                AddEdge(triangles[i + 0], triangles[i + 2]);
    
                AddEdge(triangles[i + 1], triangles[i + 0]);
                AddEdge(triangles[i + 1], triangles[i + 2]);
    
                AddEdge(triangles[i + 2], triangles[i + 0]);
                AddEdge(triangles[i + 2], triangles[i + 1]);
            }
    
            for (int i = 0; i < normals.Length; i++)
                normals[i] = (normals[i] / weightsum[i]).normalized;
    
            return normals;
    
            void AddEdge(int this_id, int other_id)
            {
                if (deltas[this_id].Add(other_id))
                {
                    Vector3 delta = (verts[this_id] - verts[other_id]).normalized;
                    if (Math3d.IsApproximatelyEqual(delta, Vector3.zero))
                        return;
    
                    normals[this_id] += delta;
                    weightsum[this_id]++;
                }
            }
        }
        #endregion Helper
    }