public override void UpdateRenderer(object sender, EventArgs e) { // In case there are no link prefabs to instantiate: if (linkPrefabs.Count == 0) { return; } // Regenerate instances if needed: if (linkInstances == null || linkInstances.Count < rope.TotalParticles) { CreateChainLinkInstances(); } int constraintCount = rope.GetStructuralConstraintCount(); // we will define and transport a reference frame along the curve using parallel transport method: if (frame == null) { frame = new ObiCurveFrame(); } frame.Reset(); frame.SetTwist(-sectionTwist * constraintCount * twistAnchor); int lastParticle = -1; int tearCount = 0; for (int i = 0; i < constraintCount; ++i) { int particle1 = -1, particle2 = -1; rope.GetStructuralConstraintParticles(i, ref particle1, ref particle2); Vector3 pos = rope.GetParticlePosition(particle1); Vector3 nextPos = rope.GetParticlePosition(particle2); Vector3 linkVector = nextPos - pos; Vector3 tangent = linkVector.normalized; // update tear prefab at the first side of tear: if (i > 0 && particle1 != lastParticle) { rope.UpdateTearPrefab(frame, ref tearCount, false); // reset frame at discontinuities: frame.Reset(); } // update frame: TODO: allow mesh rendering offset from torsion (twist) rope.TransportFrame(frame, new ObiCurveSection(nextPos, tangent, rope.GetParticleOrientation(particle1) * Vector3.up, Color.white), sectionTwist); // update tear prefab at the other side of the tear: if (i > 0 && particle1 != lastParticle) { frame.position = pos; rope.UpdateTearPrefab(frame, ref tearCount, false); } // update start/end prefabs: if (!rope.Closed) { if (i == 0 && rope.startPrefabInstance != null) { rope.PlaceObjectAtCurveFrame(frame, rope.startPrefabInstance, Space.World, false); } else if (i == constraintCount - 1 && rope.endPrefabInstance != null) { frame.position = nextPos; rope.PlaceObjectAtCurveFrame(frame, rope.endPrefabInstance, Space.World, true); } } if (linkInstances[i] != null) { linkInstances[i].SetActive(true); Transform linkTransform = linkInstances[i].transform; linkTransform.position = pos + linkVector * 0.5f; linkTransform.localScale = rope.thicknessFromParticles ? (rope.principalRadii[particle1][0] / rope.thickness) * linkScale : linkScale; linkTransform.rotation = Quaternion.LookRotation(tangent, frame.normal); } lastParticle = particle2; } for (int i = constraintCount; i < linkInstances.Count; ++i) { if (linkInstances[i] != null) { linkInstances[i].SetActive(false); } } }
public override void UpdateRenderer(object sender, EventArgs e) { if (section == null || extrudedMesh == null) { return; } rope.SmoothCurvesFromParticles(); CreateMeshIfNeeded(); ClearMeshData(); float actualToRestLengthRatio = rope.SmoothLength / rope.RestLength; int sectionSegments = section.Segments; int verticesPerSection = sectionSegments + 1; // the last vertex in each section must be duplicated, due to uv wraparound. float vCoord = -uvScale.y * rope.RestLength * uvAnchor; // v texture coordinate. int sectionIndex = 0; int tearCount = 0; // we will define and transport a reference frame along the curve using parallel transport method: if (frame == null) { frame = new ObiCurveFrame(); } frame.Reset(); frame.SetTwist(-sectionTwist * rope.SmoothSections * uvAnchor); // for closed curves, last frame of the last curve must be equal to first frame of first curve. Vector3 firstTangent = Vector3.forward; Vector4 texTangent = Vector4.zero; Vector2 uv = Vector2.zero; for (int c = 0; c < rope.curves.Count; ++c) { ObiList <ObiCurveSection> curve = rope.curves[c]; // Reinitialize frame for each curve. frame.Reset(); for (int i = 0; i < curve.Count; ++i) { // Calculate previous and next curve indices: //int nextIndex = Mathf.Min(i+1,curve.Count-1); int prevIndex = Mathf.Max(i - 1, 0); // Calculate current tangent as the vector between previous and next curve points: //Vector3 nextV; // The next tangent of the last segment of the last curve in a closed rope, is the first tangent again: /*if (rope.Closed && c == rope.curves.Count-1 && i == curve.Count-1 ) * nextV = firstTangent; * else * nextV = curve[nextIndex].positionAndRadius - curve[i].positionAndRadius;*/ //Vector3 prevV = curve[i].positionAndRadius - curve[prevIndex].positionAndRadius; //Vector3 tangent = nextV + prevV; // update frame: rope.TransportFrame(frame, curve[i], sectionTwist); //curve[i].positionAndRadius,tangent,rope.sectionTwist); // update tear prefabs (first segment of not first curve, last segment of not last curve) if (c > 0 && i == 0) { rope.UpdateTearPrefab(frame, ref tearCount, false); } if (c < rope.curves.Count - 1 && i == curve.Count - 1) { rope.UpdateTearPrefab(frame, ref tearCount, true); } // update start/end prefabs: if (c == 0 && i == 0) { // store first tangent of the first curve (for closed ropes): firstTangent = frame.tangent; if (rope.startPrefabInstance != null && !rope.Closed) { rope.PlaceObjectAtCurveFrame(frame, rope.startPrefabInstance, Space.Self, false); } } else if (c == rope.curves.Count - 1 && i == curve.Count - 1 && rope.endPrefabInstance != null && !rope.Closed) { rope.PlaceObjectAtCurveFrame(frame, rope.endPrefabInstance, Space.Self, true); } // advance v texcoord: vCoord += uvScale.y * (Vector3.Distance(curve[i].positionAndRadius, curve[prevIndex].positionAndRadius) / (normalizeV ? rope.SmoothLength : actualToRestLengthRatio)); // calculate section thickness (either constant, or particle radius based): float sectionThickness = (rope.thicknessFromParticles ? curve[i].positionAndRadius.w : rope.thickness) * sectionThicknessScale; // Loop around each segment: for (int j = 0; j <= sectionSegments; ++j) { vertices.Add(frame.position + (section.vertices[j].x * frame.normal + section.vertices[j].y * frame.binormal) * sectionThickness); normals.Add(vertices[vertices.Count - 1] - frame.position); texTangent = Vector3.Cross(normals[normals.Count - 1], frame.tangent); texTangent.w = -1; tangents.Add(texTangent); vertColors.Add(curve[i].color); uv.Set((j / (float)sectionSegments) * uvScale.x, vCoord); uvs.Add(uv); if (j < sectionSegments && i < curve.Count - 1) { tris.Add(sectionIndex * verticesPerSection + j); tris.Add((sectionIndex + 1) * verticesPerSection + j); tris.Add(sectionIndex * verticesPerSection + (j + 1)); tris.Add(sectionIndex * verticesPerSection + (j + 1)); tris.Add((sectionIndex + 1) * verticesPerSection + j); tris.Add((sectionIndex + 1) * verticesPerSection + (j + 1)); } } sectionIndex++; } } CommitMeshData(); }