Skip to content

Instantly share code, notes, and snippets.

@theacb
Created June 21, 2024 00:14
Show Gist options
  • Save theacb/ba3927f7eaf08e65b8f1e17cc1d9b20b to your computer and use it in GitHub Desktop.
Save theacb/ba3927f7eaf08e65b8f1e17cc1d9b20b to your computer and use it in GitHub Desktop.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ElementPivotDemo : MonoBehaviour
{
[SerializeField]
Transform rotatingObject;
// Private Memebers
private Mesh _mesh;
private MeshFilter _meshFilter;
private List<int[]> _elements = new List<int[]>();
private Vector3[] _pivot_arr;
// Start is called before the first frame update
void Start()
{
_meshFilter = rotatingObject.GetComponent<MeshFilter>();
_mesh = _meshFilter.mesh;
Vector3[] vertices_arr = _mesh.vertices;
int[] triangles_arr = _mesh.triangles;
_pivot_arr = new Vector3[vertices_arr.Length];
ScanElements(vertices_arr.Length, triangles_arr);
foreach (int[] el in _elements)
{
Vector3 sum = Vector3.zero;
foreach (int ind in el)
{
sum += vertices_arr[ind];
}
Vector3 center = sum / el.Length;
foreach (int ind in el)
{
_pivot_arr[ind] = center;
}
}
}
// Update is called once per frame
void Update()
{
float rot_delta = speed * Time.deltaTime;
Quaternion angles = Quaternion.Euler(new Vector3(0, 0, rot_delta));
Vector3 offset = new Vector3(0, 100, 0);
Vector3[] vertices_arr = _mesh.vertices;
for (int i = 0; i < vertices_arr.Length; i++)
{
vertices_arr[i] = RotatePointAroundPivot(vertices_arr[i], _pivot_arr[i], angles);
}
_mesh.vertices = vertices_arr;
}
Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Quaternion angles)
{
// From users aldonaletto and Guenter123987 on Unity Forums
//https://discussions.unity.com/t/rotate-a-vector-around-a-certain-point/81225
return angles * (point - pivot) + pivot;
}
void ScanElements(int vertex_count, int[] triangles_arr)
{
// Creates bool array to tell which verts have been scanned by triangles
bool[] scanned_verts = new bool[vertex_count];
bool[] queued_verts = new bool[vertex_count];
// Seperates vertices into elements / islands
for (int i = 0; i < vertex_count; i++)
{
// Skip already scanned verts
if (!scanned_verts[i])
{
// Prepare variables
Queue<int> vert_queue = new Queue<int>();
List<int> element_members = new List<int>();
vert_queue.Enqueue(i);
element_members.Add(i);
queued_verts[i] = true;
int next_tri_index = 0;
// Scan through starting with the index, and then adding any connected vertices to the queue
while (vert_queue.Count > 0)
{
int vert_index = vert_queue.Peek();
int[] triangle = ScanTris(triangles_arr, vert_index, next_tri_index);
// When the tri list is finished being scanned, remove index from queue
if (triangle[3] == -1)
{
scanned_verts[vert_index] = true;
next_tri_index = 0;
vert_queue.Dequeue();
}
else
{
// Iterate through the triangle and queue verts that need to be queued, skipping the rest
for (int j = 0; j < 3; j++)
{
int current_vert = triangle[j];
if (!queued_verts[current_vert])
{
element_members.Add(current_vert);
vert_queue.Enqueue(current_vert);
queued_verts[current_vert] = true;
}
}
next_tri_index = triangle[3] + 3;
}
}
// Convert list to Array and add to _elements list
int[] element_members_arr = element_members.ToArray();
_elements.Add(element_members_arr);
}
}
}
int[] ScanTris(int[] triangles_arr, int search_vert_index, int start_tri_index)
{
// Triangle is an array of 3 indices plus the current index in the triangle array
// found_triangle[3] being the default of -1 indicates that the index was not found
int[] found_triangle = new int[4] { 0, 0, 0, -1 };
// Iterate by 3 to scan each tri
for (int i = start_tri_index; i < triangles_arr.Length; i += 3)
{
int t_0 = triangles_arr[i];
int t_1 = triangles_arr[i + 1];
int t_2 = triangles_arr[i + 2];
// If the search index is any of the 3 points, return the whole triangle
if (t_0 == search_vert_index || t_1 == search_vert_index || t_2 == search_vert_index)
{
found_triangle[0] = t_0;
found_triangle[1] = t_1;
found_triangle[2] = t_2;
found_triangle[3] = i;
return found_triangle;
}
}
// Retuen default values
return found_triangle;
}
}
@theacb
Copy link
Author

theacb commented Jun 21, 2024

Here is some code to group a mesh by it's elements / islands. Probably not the best method for this, and it splits at all UV boundaries, but I wanted to put it up to refer to later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment