예제 #1
0
        public static void DrawPathHandle(ObiPath path, Matrix4x4 referenceFrame, float thicknessScale, int resolution, bool drawOrientation = true)
        {
            if (path == null || path.GetSpanCount() == 0)
            {
                return;
            }

            Matrix4x4 prevMatrix = Handles.matrix;

            Handles.matrix = referenceFrame;

            // Draw the curve:
            int curveSegments = path.GetSpanCount() * resolution;

            Vector3[] samples      = new Vector3[curveSegments + 1];
            Vector3[] leftSamples  = new Vector3[curveSegments + 1];
            Vector3[] rightSamples = new Vector3[curveSegments + 1];
            Vector3[] upSamples    = new Vector3[curveSegments + 1];

            for (int i = 0; i <= curveSegments; ++i)
            {
                float mu = i / (float)curveSegments;
                samples[i] = path.points.GetPositionAtMu(path.Closed, mu);

                if (drawOrientation)
                {
                    Vector3 tangent   = path.points.GetTangentAtMu(path.Closed, mu);
                    Vector3 right     = Vector3.Cross(tangent, path.normals.GetAtMu(path.Closed, mu)).normalized;
                    Vector3 up        = Vector3.Cross(right, tangent).normalized;
                    float   thickness = path.thicknesses.GetAtMu(path.Closed, mu) * thicknessScale + 0.05f;

                    leftSamples[i]  = samples[i] - right * thickness;
                    rightSamples[i] = samples[i] + right * thickness;
                    upSamples[i]    = samples[i] + up * thickness;

                    if (i % 5 == 0)
                    {
                        Handles.DrawLine(leftSamples[i], rightSamples[i]);
                        Handles.DrawLine(samples[i], samples[i] + up * thickness);
                    }
                }
            }

            if (drawOrientation)
            {
                DrawControlPointArcs(path, thicknessScale);
            }

            DrawPathPolylines(samples, leftSamples, rightSamples, upSamples, drawOrientation);
            DrawPathPolylines(samples, leftSamples, rightSamples, upSamples, drawOrientation);

            Handles.matrix = prevMatrix;
        }
        public static float ScreenPointToCurveMu(ObiPath path, Vector2 screenPoint, Matrix4x4 referenceFrame, int samples = 30)
        {
            if (path.ControlPointCount >= 2)
            {
                samples = Mathf.Max(1, samples);
                float step = 1 / (float)samples;

                float closestMu   = 0;
                float minDistance = float.MaxValue;

                for (int k = 0; k < path.GetSpanCount(); ++k)
                {
                    int nextCP = (k + 1) % path.ControlPointCount;

                    var wp1 = path.points[k];
                    var wp2 = path.points[nextCP];

                    Vector3 _p  = referenceFrame.MultiplyPoint3x4(wp1.position);
                    Vector3 p   = referenceFrame.MultiplyPoint3x4(wp1.outTangentEndpoint);
                    Vector3 p_  = referenceFrame.MultiplyPoint3x4(wp2.inTangentEndpoint);
                    Vector3 p__ = referenceFrame.MultiplyPoint3x4(wp2.position);

                    Vector2 lastPoint = HandleUtility.WorldToGUIPoint(path.m_Points.Evaluate(_p, p, p_, p__, 0));
                    for (int i = 1; i <= samples; ++i)
                    {
                        Vector2 currentPoint = HandleUtility.WorldToGUIPoint(path.m_Points.Evaluate(_p, p, p_, p__, i * step));

                        float mu;
                        float distance = Vector2.SqrMagnitude((Vector2)ObiUtils.ProjectPointLine(screenPoint, lastPoint, currentPoint, out mu) - screenPoint);

                        if (distance < minDistance)
                        {
                            minDistance = distance;
                            closestMu   = (k + (i - 1) * step + mu / samples) / (float)path.GetSpanCount();
                        }
                        lastPoint = currentPoint;
                    }
                }

                return(closestMu);
            }
            else
            {
                Debug.LogWarning("Curve needs at least 2 control points to be defined.");
            }
            return(0);
        }