Beispiel #1
0
        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);
                }
            }
        }
Beispiel #2
0
        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();
        }