Last active
January 19, 2020 17:33
-
-
Save josemorval/4a2c89a8f1bd560b1c79ddcb1c5fe7b6 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; | |
| //Protoype of Free-Form Deformation based on http://faculty.cs.tamu.edu/schaefer/teaching/689_Fall2006/p151-sederberg.pdf | |
| public class FFDModifier : MonoBehaviour | |
| { | |
| public GameObject modelObject; | |
| public GameObject ffdGizmo; | |
| public int divX; | |
| public int divY; | |
| public int divZ; | |
| MeshRenderer modelRenderer; | |
| MeshFilter modelFilter; | |
| int[,] binNM; | |
| GameObject[,,] gizmoMarkers; | |
| Vector3[] vscoef; | |
| bool gridDefined; | |
| void Start() | |
| { | |
| gridDefined = false; | |
| modelRenderer = modelObject.GetComponent<MeshRenderer>(); | |
| modelFilter = modelObject.GetComponent<MeshFilter>(); | |
| } | |
| void Update() | |
| { | |
| //Setup markers based on bounding of the geometry | |
| if (Input.GetKeyDown(KeyCode.G)) | |
| { | |
| foreach (Transform child in transform) | |
| { | |
| GameObject.Destroy(child.gameObject); | |
| } | |
| Bounds b = modelRenderer.bounds; | |
| Vector3 vSize = b.size; | |
| Vector3 vMinimum = b.min; | |
| gizmoMarkers = new GameObject[divX,divY,divZ]; | |
| //Create gizmo markers | |
| for (int i = 0; i < divX; i++) | |
| { | |
| for(int j = 0; j < divY; j++) | |
| { | |
| for(int k = 0; k < divZ; k++) { | |
| GameObject g = GameObject.Instantiate(ffdGizmo, transform); | |
| Vector3 pos = vMinimum + new Vector3(vSize.x*i/(divX-1f), vSize.y*j/(divY-1f), vSize.z*k/(divZ-1f)); | |
| g.transform.position = pos; | |
| gizmoMarkers[i, j, k] = g; | |
| } | |
| } | |
| } | |
| //Compute (s,t,u) coefficientes for points | |
| Vector3 S = new Vector3(vSize.x, 0f, 0f); | |
| Vector3 T = new Vector3(0f, vSize.y, 0f); | |
| Vector3 U = new Vector3(0f, 0f, vSize.z); | |
| Vector3 cST = Vector3.Cross(S, T); | |
| Vector3 cTU = Vector3.Cross(T, U); | |
| Vector3 cSU = Vector3.Cross(S, U); | |
| Mesh modelMesh = modelFilter.mesh; | |
| Vector3[] vs = modelMesh.vertices; | |
| vscoef = new Vector3[vs.Length]; | |
| for(int i = 0; i < vs.Length; i++) | |
| { | |
| vscoef[i].x = Vector3.Dot(cTU, vs[i] - vMinimum) / Vector3.Dot(cTU, S); | |
| vscoef[i].y = Vector3.Dot(cSU, vs[i] - vMinimum) / Vector3.Dot(cSU, T); | |
| vscoef[i].z = Vector3.Dot(cST, vs[i] - vMinimum) / Vector3.Dot(cST, U); | |
| } | |
| //Compute binomial coefficients | |
| int numberCoefficients = Mathf.Max(Mathf.Max(divX, divY), divZ); | |
| binNM = new int[numberCoefficients, numberCoefficients]; | |
| binNM[0, 0] = 1; | |
| for(int i = 1; i < numberCoefficients; i++) | |
| { | |
| for(int j = 0; j <= i; j++) | |
| { | |
| if(j==0 || j == i) | |
| { | |
| binNM[i, j] = 1; | |
| } | |
| else | |
| { | |
| binNM[i, j] = binNM[i - 1, j - 1] + binNM[i - 1, j]; | |
| } | |
| } | |
| } | |
| gridDefined = true; | |
| } | |
| //Now we can move the gizmo markers to modify the geometry | |
| //This is gonna be recoded with job system | |
| if (gridDefined) | |
| { | |
| Mesh mesh = modelFilter.mesh; | |
| Vector3[] vs = mesh.vertices; | |
| for(int l = 0; l < vs.Length; l++) | |
| { | |
| Vector3 vX = Vector3.zero; | |
| Vector3 vY = Vector3.zero; | |
| Vector3 vZ = Vector3.zero; | |
| //Compute final vertex coordinates from gizmo markers points | |
| for (int i = 0; i < divX; i++) | |
| { | |
| vY = Vector3.zero; | |
| for (int j = 0; j < divY; j++) | |
| { | |
| vZ = Vector3.zero; | |
| for (int k = 0; k < divZ; k++) | |
| { | |
| vZ += binNM[divZ - 1, k] * Mathf.Pow(1f - vscoef[l].z, divZ - 1f - k) * Mathf.Pow(vscoef[l].z, k) * gizmoMarkers[i, j, k].transform.position; | |
| } | |
| vZ *= binNM[divY - 1, j] * Mathf.Pow(1f - vscoef[l].y, divY - 1f - j) * Mathf.Pow(vscoef[l].y, j); | |
| vY += vZ; | |
| } | |
| vY *= binNM[divX - 1, i] * Mathf.Pow(1f - vscoef[l].x, divX - 1f - i) * Mathf.Pow(vscoef[l].x, i); | |
| vX += vY; | |
| } | |
| vs[l] = vX; | |
| } | |
| mesh.vertices = vs; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment