public override void LoadBlueprint(ObiSolver solver) { // Grab a copy of the serialized topology reference. This happens when duplicating a cloth. if (topology != null && topology.ContainsData) { topology = new HalfEdgeMesh(topology); } // Or a copy of the shared topology, if there is no valid reference to a topology. else if (m_TearableClothBlueprint != null && m_TearableClothBlueprint.Topology != null) { topology = new HalfEdgeMesh(m_TearableClothBlueprint.Topology); } //Copy tear resistance array: tearResistance = new float[m_TearableClothBlueprint.tearResistance.Length]; for (int i = 0; i < tearResistance.Length; ++i) { tearResistance[i] = m_TearableClothBlueprint.tearResistance[i]; } //Copy deformable triangles array: deformableTriangles = new int[m_TearableClothBlueprint.deformableTriangles.Length]; for (int i = 0; i < deformableTriangles.Length; ++i) { deformableTriangles[i] = m_TearableClothBlueprint.deformableTriangles[i]; } base.LoadBlueprint(solver); SetupRuntimeConstraints(); }
public HalfEdgeMesh(HalfEdgeMesh halfEdge) { this.containsData = halfEdge.containsData; this.inputMesh = halfEdge.inputMesh; this.scale = halfEdge.scale; this.vertices = new List <Vertex>(halfEdge.vertices); this.halfEdges = new List <HalfEdge>(halfEdge.halfEdges); this.borderEdges = new List <HalfEdge>(halfEdge.borderEdges); this.faces = new List <Face>(halfEdge.faces); this.restNormals = new List <Vector3>(halfEdge.restNormals); this.restOrientations = new List <Quaternion>(halfEdge.restOrientations); this.rawToWelded = new List <int>(halfEdge.rawToWelded); }
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]; phases = 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; phases[i] = ObiUtils.MakePhase(1, /*selfCollisions ? Oni.ParticlePhase.SelfCollide : 0*/ 0); colors[i] = Color.white; if (i % 500 == 0) { yield return(new CoroutineJob.ProgressInfo("ObiCloth: generating particles...", i / (float)topology.vertices.Count)); } } // Deformable triangles: 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 volume constraints: IEnumerator vc = CreateVolumeConstraints(); while (vc.MoveNext()) { yield return(vc.Current); } }