Skip to content

Instantly share code, notes, and snippets.

@twobob
Created May 11, 2018 00:14
Show Gist options
  • Save twobob/5e49cfa4e50846c235a073e0c5521b6f to your computer and use it in GitHub Desktop.
Save twobob/5e49cfa4e50846c235a073e0c5521b6f to your computer and use it in GitHub Desktop.
DefamationMangler deformation mangler (totally untested for 4 years)
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
public class DefamationMangler : MonoBehaviour
{
[MenuItem("Tools/DefamationMangler %#d")]
static void AlignMeshVertices()
{
Undo.RecordObjects(Selection.transforms, "Mangle To Surface");
VerticesInit();
}
[MenuItem("Tools/Reset A Plane %#r")]
static void ResetMeshVertices()
{
Undo.RecordObjects(Selection.transforms, "deMangle To Surface");
foreach (GameObject go in Selection.gameObjects)
{
MeshFilter filter = go.GetComponent(typeof(MeshFilter)) as MeshFilter;
if (filter != null)
{
Mesh mesh = filter.sharedMesh;
go.transform.localScale = Vector3.one;
for (int m = 0; m < mesh.subMeshCount; m++)
{
Vector3[] verts = mesh.vertices;
for (int i = 0; i < verts.Length; i++)
{
if (go.transform.rotation.eulerAngles.x == 0)
{
verts[i].y = 0;
}
else if (go.transform.rotation.eulerAngles.x == 270)
{
verts[i].z =0;
}
else
{
print("UNKNOWN OBJECT ROTATION ARGH! FIX IT in the rotation!");
}
}
List<Vector3> vertList = new List<Vector3>(verts);
Debug.Log(vertList.Count);
mesh.SetVertices(vertList);
}
}
}
}
private static void VerticesInit()
{
foreach (GameObject go in Selection.gameObjects)
{
MeshFilter filter = go.GetComponent(typeof(MeshFilter)) as MeshFilter;
if (filter != null)
{
ResetMeshVertices();
// add some clearance
go.transform.position += (Vector3.up * 10f);
DefamationMangle(ref filter, go);
}
else
{
print("gameobject " + go.name + " has no mesh filter");
}
}
}
public static Vector3 FindClosest(float target, IList<Vector3> list)
{
Vector3 result = list[0];
float minDelta = float.MaxValue;
foreach (Vector3 x in list)
{
// Can't use Math.Abs()
float delta = (x.y < target) ? (target - x.y) : (x.y - target);
if (delta < minDelta)
{
minDelta = delta;
result = x;
}
}
return result;
}
static void DefamationMangle(ref MeshFilter filter, GameObject go)
{
print("==BEGIN==");
if (filter != null)
{
Mesh mesh = filter.sharedMesh;
go.transform.localScale = Vector3.one;
for (int m = 0; m < mesh.subMeshCount; m++)
{
List<Vector3> RealWorldLocations = new List<Vector3>(mesh.vertices.Length);
Debug.Log(mesh.subMeshCount);
int[] triangles = mesh.GetTriangles(m);
Vector3[] verts;
float midY;
float highestY = 0f;
float lowestY = 0;
float range;
print("1st Range Setup");
SetupTheRealWorldRanges(go, mesh, out RealWorldLocations, out midY, out highestY, out lowestY, out range);
print("MID Y:" + midY);
//HAAAACKKKK
// Vector3 TheVertexLocation = FindClosest(midY, RealWorldLocations);
Vector3 TheVertexLocation = Vector3.zero; // = FindClosest(highestY, RealWorldLocations);
float closestResult = float.MaxValue;
foreach (var item in RealWorldLocations)
{
RaycastHit InitialTestHit;
bool WeDidHit = Physics.Raycast(item + (Vector3.up * 10), -Vector3.up, out InitialTestHit);
float distance = item.y - InitialTestHit.point.y;
// print("For location: " + item + " is " + (distance - 10f));
if (distance < closestResult)
{
closestResult = distance;
TheVertexLocation = item;
}
}
// print("Shortest Y is:"+ TheVertexLocation);
//Vector3 TheVertexLocation = go.transform.position;
// move to the approximate middle;
// print(TheVertexLocation);
// OFFSET!!
// print(TheVertexLocation - go.transform.position);
RaycastHit VertexInitialTestHit;
bool DidHit = Physics.Raycast(TheVertexLocation + (Vector3.up * 10), -Vector3.up, out VertexInitialTestHit);
print("REQUIRED OFFSET FOR BEST ORIGIN: " + ((TheVertexLocation - VertexInitialTestHit.point) - (Vector3.up * 10)));
print("REQUIRED OFFSET FOR BEST ORIGIN: " + ((TheVertexLocation - VertexInitialTestHit.point) - (Vector3.up * 10)).y);
// DISABLED FOR NOW
go.transform.position -= TheVertexLocation - VertexInitialTestHit.point;
print("2st Range Setup");
SetupTheRealWorldHitRanges(go, RealWorldLocations, out midY, out highestY, out lowestY, out range);
print("MID Y:" + midY);
print("FINAL RANGE: " + range);
print("FINAL highestY: " + highestY);
print("FINAL lowestY: " + lowestY);
verts = mesh.vertices;
for (int i = 0; i < verts.Length; i++)
{
RaycastHit hit;
Vector3 worldPt = go.transform.TransformPoint(mesh.vertices[i]);// currentVert]);
// print("CURRENT: " + mesh.vertices[i]);// currentVert]);
// currentVert--;
if (Physics.Raycast(worldPt + (Vector3.up * 10), -Vector3.up, out hit))
{
Vector3 targetPosition = hit.point;
// Take the test from the highest point.
Vector3 ActualOffset = worldPt - targetPosition;
// print("Actual Y: "+ActualOffset.y);
// create normalised version of the y - using the range.
// offset to - 0.5 - 0.5 range
Vector2 NormalisingHolder = new Vector2(ActualOffset.y, range).normalized;
// print(NormalisingHolder.x);
float normalisedResult = (NormalisingHolder.x * 1) + 0.5f;
// Debug.Log("NORMALISED RESULT FOR VERTEX:" + normalisedResult);
// print("setting vertex index:" + i);
if (go.transform.rotation.eulerAngles.x == 0)
{
verts[i].y = -normalisedResult;
}
else if (go.transform.rotation.eulerAngles.x == 270)
{
verts[i].z = -normalisedResult;
}
else
{
print("UNKNOWN OBJECT ROTATION ARGH! FIX IT in the rotation!");
}
// Debug.Log("DIFF: " + ActualOffset);
}
// mesh.SetTriangles(triangles, m);
}
List<Vector3> vertList = new List<Vector3>(verts);
// Debug.Log(vertList.Count);
mesh.SetVertices(vertList);
mesh.RecalculateNormals();
mesh.RecalculateBounds();
go.transform.localScale = new Vector3(1, 1, range * 1.2f);
go.transform.position += (Vector3.up * (range * .95f));
Transform[] transforms = Selection.transforms;
foreach (Transform myTransform in transforms)
{
RaycastHit hit;
if (Physics.Raycast(myTransform.position, -Vector3.up, out hit))
{
Vector3 targetPosition = hit.point;
if (myTransform.gameObject.GetComponent<MeshFilter>() != null)
{
verts = mesh.vertices;
// go.transform.position = go.transform.position - (Vector3.up * (range * 0.4f));
}
}
}
}
}
}
private static void SetupTheRealWorldRanges(GameObject go, Mesh mesh, out List<Vector3> RealWorldLocations, out float midY, out float highestY, out float lowestY, out float range)
{
RealWorldLocations = new List<Vector3>(mesh.vertices.Length);
Vector3[] verts = mesh.vertices;
// print("VERT COUNT: "+verts.Length);
highestY = float.MinValue;
lowestY = float.MaxValue;
for (int i = 0; i < verts.Length; i++)
{
Vector3 worldPt = go.transform.TransformPoint(mesh.vertices[i]);
RealWorldLocations.Add(worldPt);
if (worldPt.y > highestY)
{
highestY = worldPt.y;
}
if (worldPt.y < lowestY)
{
lowestY = worldPt.y;
}
}
range = highestY - lowestY;
midY = lowestY + (range * 0.5f);
}
private static void SetupTheRealWorldHitRanges(GameObject go, List<Vector3> RealWorldLocations, out float midY, out float highestY, out float lowestY, out float range)
{
// print("LOCATIONS COUNT: "+RealWorldLocations.Count);
highestY = float.MinValue;
lowestY = float.MaxValue;
for (int i = 0; i < RealWorldLocations.Count; i++)
{
RaycastHit hit;
// bool DidHit = Physics.Raycast(worldPt + (Vector3.up * 10), -Vector3.up, out hit)
if (Physics.Raycast(RealWorldLocations[i] + (Vector3.up * 10), -Vector3.up, out hit))
{
Vector3 worldPt = hit.point; // go.transform.TransformPoint(RealWorldLocations[i]);
// print(worldPt);
if (worldPt.y > highestY)
{
highestY = worldPt.y;
}
if (worldPt.y < lowestY)
{
lowestY = worldPt.y;
}
}
}
range = highestY - lowestY;
midY = lowestY + (range * 0.5f);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment