Skip to content

Instantly share code, notes, and snippets.

@rectalogic
Created September 14, 2016 13:44
Show Gist options
  • Save rectalogic/47db6d228c85742233c353b6398b92fb to your computer and use it in GitHub Desktop.
Save rectalogic/47db6d228c85742233c353b6398b92fb to your computer and use it in GitHub Desktop.
Unity3D 5.x component to generate a mesh and control a vertex on the new Cloth component
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[RequireComponent(typeof(SkinnedMeshRenderer), typeof(Cloth))]
public class ClothMesh : MonoBehaviour {
public float width = 5;
public float height = 5;
public int xSize = 20;
public int ySize = 20;
public int controlVertex = 0;
private SkinnedMeshRenderer skinnedRenderer;
private Cloth cloth;
private Transform rootBone;
private Transform controlBone;
private int controlIndex;
private Mesh mesh;
void Awake() {
skinnedRenderer = GetComponent<SkinnedMeshRenderer>();
cloth = GetComponent<Cloth>();
rootBone = new GameObject("RootBone").transform;
rootBone.parent = transform;
rootBone.localRotation = Quaternion.identity;
rootBone.localPosition = Vector3.zero;
controlBone = new GameObject("ControlBone").transform;
controlBone.parent = transform;
controlBone.localRotation = Quaternion.identity;
controlBone.localPosition = Vector3.zero;
skinnedRenderer.bones = new Transform[] {rootBone, controlBone};
mesh = CreateMesh(width, height, xSize, ySize);
skinnedRenderer.sharedMesh = mesh;
ControlVertex(controlVertex);
}
private IEnumerable<int> IndexNeighbors(int index) {
int yCount = ySize + 1;
int i = index % yCount;
int j = index / yCount;
for (int x = Mathf.Max(0, i - 1); x <= Mathf.Min(i + 1, xSize); x++) {
for (int y = Mathf.Max(0, j - 1); y <= Mathf.Min(j + 1, ySize); y++) {
yield return y * yCount + x;
}
}
}
private void ControlVertex(int index) {
ClothSkinningCoefficient[] coefficients = cloth.coefficients;
BoneWeight[] boneWeights = mesh.boneWeights;
// Unset previous control
foreach (int i in IndexNeighbors(controlIndex)) {
boneWeights[i].boneIndex0 = 0;
coefficients[i].maxDistance = Mathf.Infinity;
}
foreach (int i in IndexNeighbors(index)) {
boneWeights[i].boneIndex0 = 1;
coefficients[i].maxDistance = 0.3f;
}
coefficients[index].maxDistance = 0;
controlBone.localPosition = cloth.vertices[index];
mesh.bindposes = new Matrix4x4[] {rootBone.worldToLocalMatrix * transform.localToWorldMatrix, controlBone.worldToLocalMatrix * transform.localToWorldMatrix};
mesh.boneWeights = boneWeights;
cloth.coefficients = coefficients;
controlIndex = index;
}
private Mesh CreateMesh(float width, float height, int xSize, int ySize) {
Mesh mesh = new Mesh();
mesh.name = name + "Mesh";
Vector3[] vertices = new Vector3[(xSize + 1) * (ySize + 1)];
Vector2[] uv = new Vector2[vertices.Length];
float xStep = width / xSize;
float hWidth = width / 2.0f;
float yStep = height / ySize;
float hHeight = height / 2.0f;
for (int i = 0, y = 0; y <= ySize; y++) {
for (int x = 0; x <= xSize; x++, i++) {
vertices[i] = new Vector3((x * xStep) - hWidth, (y * yStep) - hHeight);
uv[i] = new Vector2(x / (float)xSize, y / (float)ySize);
}
}
int[] triangles = new int[xSize * ySize * 6];
for (int ti = 0, vi = 0, y = 0; y < ySize; y++, vi++) {
for (int x = 0; x < xSize; x++, ti += 6, vi++) {
triangles[ti] = vi;
triangles[ti + 3] = triangles[ti + 2] = vi + 1;
triangles[ti + 4] = triangles[ti + 1] = vi + xSize + 1;
triangles[ti + 5] = vi + xSize + 2;
}
}
mesh.vertices = vertices;
mesh.uv = uv;
mesh.triangles = triangles;
mesh.RecalculateNormals();
BoneWeight[] boneWeights = new BoneWeight[vertices.Length];
for (int i = 0; i < boneWeights.Length; i++) {
boneWeights[i].weight0 = 1;
}
mesh.boneWeights = boneWeights;
return mesh;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment