Created
June 21, 2024 00:14
-
-
Save theacb/ba3927f7eaf08e65b8f1e17cc1d9b20b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.