138 lines
5.1 KiB
C#
138 lines
5.1 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using System;
|
|
|
|
namespace Obi
|
|
{
|
|
|
|
[CreateAssetMenu(fileName = "skinned cloth blueprint", menuName = "Obi/Skinned Cloth Blueprint", order = 122)]
|
|
public class ObiSkinnedClothBlueprint : ObiClothBlueprint
|
|
{
|
|
|
|
public override bool usesTethers
|
|
{
|
|
get { return true; }
|
|
}
|
|
|
|
protected override IEnumerator Initialize(){
|
|
|
|
if (inputMesh == null || !inputMesh.isReadable)
|
|
{
|
|
// TODO: return an error in the coroutine.
|
|
Debug.LogError("The input mesh is null, or not readable.");
|
|
yield break;
|
|
}
|
|
|
|
ClearParticleGroups();
|
|
|
|
topology = new HalfEdgeMesh();
|
|
topology.inputMesh = inputMesh;
|
|
topology.Generate();
|
|
|
|
positions = new Vector3[topology.vertices.Count];
|
|
restPositions = new Vector4[topology.vertices.Count];
|
|
velocities = new Vector3[topology.vertices.Count];
|
|
invMasses = new float[topology.vertices.Count];
|
|
principalRadii = new Vector3[topology.vertices.Count];
|
|
filters = new int[topology.vertices.Count];
|
|
colors = new Color[topology.vertices.Count];
|
|
|
|
areaContribution = new float[topology.vertices.Count];
|
|
|
|
// Create a particle for each vertex:
|
|
m_ActiveParticleCount = topology.vertices.Count;
|
|
for (int i = 0; i < topology.vertices.Count; i++)
|
|
{
|
|
HalfEdgeMesh.Vertex vertex = topology.vertices[i];
|
|
|
|
// Get the particle's area contribution.
|
|
areaContribution[i] = 0;
|
|
foreach (HalfEdgeMesh.Face face in topology.GetNeighbourFacesEnumerator(vertex))
|
|
{
|
|
areaContribution[i] += topology.GetFaceArea(face) / 3;
|
|
}
|
|
|
|
// Get the shortest neighbour edge, particle radius will be half of its length.
|
|
float minEdgeLength = Single.MaxValue;
|
|
foreach (HalfEdgeMesh.HalfEdge edge in topology.GetNeighbourEdgesEnumerator(vertex))
|
|
{
|
|
|
|
// vertices at each end of the edge:
|
|
Vector3 v1 = Vector3.Scale(scale, topology.vertices[topology.GetHalfEdgeStartVertex(edge)].position);
|
|
Vector3 v2 = Vector3.Scale(scale,topology.vertices[edge.endVertex].position);
|
|
|
|
minEdgeLength = Mathf.Min(minEdgeLength, Vector3.Distance(v1, v2));
|
|
}
|
|
|
|
invMasses[i] = (/*skinnedMeshRenderer == null &&*/ areaContribution[i] > 0) ? (1.0f / (DEFAULT_PARTICLE_MASS * areaContribution[i])) : 0;
|
|
positions[i] = Vector3.Scale(scale,vertex.position);
|
|
restPositions[i] = positions[i];
|
|
restPositions[i][3] = 1; // activate rest position.
|
|
principalRadii[i] = Vector3.one * minEdgeLength * 0.5f;
|
|
filters[i] = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything, 1);
|
|
colors[i] = Color.white;
|
|
|
|
if (i % 500 == 0)
|
|
yield return new CoroutineJob.ProgressInfo("ObiCloth: generating particles...", i / (float)topology.vertices.Count);
|
|
}
|
|
|
|
colorizer = new GraphColoring(m_ActiveParticleCount);
|
|
|
|
IEnumerator dt = GenerateDeformableTriangles();
|
|
while (dt.MoveNext())
|
|
yield return dt.Current;
|
|
|
|
//Create distance constraints:
|
|
IEnumerator dc = CreateDistanceConstraints();
|
|
|
|
while (dc.MoveNext())
|
|
yield return dc.Current;
|
|
|
|
// Create aerodynamic constraints:
|
|
IEnumerator ac = CreateAerodynamicConstraints();
|
|
|
|
while (ac.MoveNext())
|
|
yield return ac.Current;
|
|
|
|
|
|
//Create bending constraints:
|
|
IEnumerator bc = CreateBendingConstraints();
|
|
|
|
while (bc.MoveNext())
|
|
yield return bc.Current;
|
|
|
|
|
|
// Create skin constraints:
|
|
IEnumerator sc = CreateSkinConstraints();
|
|
|
|
while (sc.MoveNext())
|
|
yield return sc.Current;
|
|
|
|
}
|
|
|
|
protected IEnumerator CreateSkinConstraints()
|
|
{
|
|
skinConstraintsData = new ObiSkinConstraintsData();
|
|
ObiSkinConstraintsBatch skinBatch = new ObiSkinConstraintsBatch();
|
|
skinConstraintsData.AddBatch(skinBatch);
|
|
|
|
for (int i = 0; i < topology.vertices.Count; ++i)
|
|
{
|
|
|
|
skinBatch.AddConstraint(i, Vector3.Scale(scale,topology.vertices[i].position), Vector3.up, 0.05f, 0.1f, 0, 0);
|
|
skinBatch.activeConstraintCount++;
|
|
|
|
if (i % 500 == 0)
|
|
yield return new CoroutineJob.ProgressInfo("ObiCloth: generating skin constraints...", i / (float)topology.vertices.Count);
|
|
}
|
|
|
|
Vector3[] normals = topology.inputMesh.normals;
|
|
for (int i = 0; i < normals.Length; ++i)
|
|
{
|
|
skinBatch.skinNormals[topology.rawToWelded[i]] = normals[i];
|
|
}
|
|
}
|
|
|
|
}
|
|
} |