Example #1
0
        public OrthonormalFrame PropagateBishop(Vector3 prevPos, Vector3 nextPos, OrthonormalFrame prevFrame)
        {
            Vector3 tangent     = (nextPos - position).normalized;
            Vector3 prevTangent = (position - prevPos).normalized;
            Vector3 binormal    = Vector3.Cross(prevTangent, tangent).normalized;

            float angle = TelescopeUtils.AngleBetween(prevTangent, tangent, binormal);

            Quaternion rotation = Quaternion.AngleAxis(angle, binormal);

            OrthonormalFrame rotated = prevFrame.RotatedBy(rotation);

            bishopFrame = rotated;
            return(rotated);
        }
Example #2
0
        /// <summary>
        /// Create a set of vertices arranged evenly spaced in a circle, with the specified radius,
        /// centered at centerPoint, and with the specified normal direction. The number of vertices
        /// is given by verticesPerCircle.
        /// </summary>
        /// <param name="centerPoint"></param>
        /// <param name="direction"></param>
        /// <param name="radius"></param>
        /// <returns></returns>
        List <IndexedVertex> GenerateCircle(int circNum, Vector3 centerPoint, Vector3 direction,
                                            Vector3 normal, float radius, bool addInnerGrooves = false, bool addOuterGroove = false)
        {
            float angleStep  = (2 * Mathf.PI) / Constants.VERTS_PER_CIRCLE;
            float degreeStep = angleStep * Mathf.Rad2Deg;

            int twistCuts = Mathf.CeilToInt(Mathf.Abs(nextTwistAngle) / degreeStep);

            twistCuts *= Mathf.RoundToInt(Mathf.Sign(nextTwistAngle));

            List <IndexedVertex> verts = new List <IndexedVertex>();

            int grooveRange = Constants.GROOVE_CUT_RADIUS;

            // First create points in a circle in the XY plane, facing the forward direction.
            // Then apply the rotation that will rotate the normal onto the desired direction.
            // Finally, offset it in space to the desired location.
            Quaternion circleRotation = Quaternion.FromToRotation(Vector3.forward, direction);
            Vector3    initNormal     = Vector3.up;
            Vector3    rotatedNormal  = circleRotation * initNormal;

            float      angle          = TelescopeUtils.AngleBetween(rotatedNormal, normal, direction);
            Quaternion normalRotation = Quaternion.AngleAxis(angle, direction);

            for (int i = 0; i < Constants.VERTS_PER_CIRCLE; i++)
            {
                float currentAngle = i * angleStep;
                float radiusOffset = 0;
                if (i < grooveRange ||
                    Mathf.Abs(i - Constants.VERTS_PER_CIRCLE / 2) < grooveRange ||
                    Mathf.Abs(i - Constants.VERTS_PER_CIRCLE) < grooveRange)
                {
                    if (addInnerGrooves)
                    {
                        radiusOffset = (thickness - Constants.SHELL_GAP) * Constants.INDENT_RATIO;
                    }
                    else if (addOuterGroove)
                    {
                        radiusOffset = (thickness - Constants.SHELL_GAP / 2) * Constants.INDENT_RATIO;
                    }
                }

                else if (circNum >= Constants.CUTS_PER_CYLINDER - 1 &&
                         circNum < Constants.CUTS_PER_CYLINDER + Constants.FIN_CUTS)
                {
                    if (addInnerGrooves &&
                        (IsInRadius(i, 0, twistCuts, grooveRange) ||
                         IsInRadius(i, Constants.VERTS_PER_CIRCLE,
                                    Constants.VERTS_PER_CIRCLE + twistCuts, grooveRange) ||
                         IsInRadius(i, Constants.VERTS_PER_CIRCLE / 2,
                                    Constants.VERTS_PER_CIRCLE / 2 + twistCuts, grooveRange)))
                    {
                        radiusOffset = (thickness - Constants.SHELL_GAP) * Constants.INDENT_RATIO;
                    }
                }

                // Make the vertices in clockwise order
                Vector3 vert = new Vector3(Mathf.Cos(currentAngle), -Mathf.Sin(currentAngle));
                // Scale by radius.
                vert *= (radius + radiusOffset);
                // Rotate it to orbit the desired direction.
                vert = circleRotation * vert;
                // Rotate it again so that the curvature normal is aligned.
                vert = normalRotation * vert;
                // Offset in space to the center point.
                vert += centerPoint;
                IndexedVertex iv = new IndexedVertex(vert, currentIndex);
                currentIndex++;
                verts.Add(iv);
            }
            return(verts);
        }
Example #3
0
        // Compute all internal bending axes/angles from a list of points.
        public void InitFromPoints(List <Vector3> points, float segLength)
        {
            segmentLength = segLength;

            StartingPoint   = points[0];
            startingTangent = points[1] - points[0];
            startingTangent.Normalize();

            discretizedPoints = new List <DCurvePoint>();

            Vector3 prevBinormal = Vector3.zero;

            // We need to store bending angles / directions of all the interior
            // vertices of the curve (but not the endpoints).
            for (int i = 1; i < points.Count - 1; i++)
            {
                Vector3 previousVec = points[i] - points[i - 1];
                Vector3 nextVec     = points[i + 1] - points[i];

                previousVec.Normalize();
                nextVec.Normalize();

                // If zero, then treat it as a straight segment
                if (nextVec.magnitude < 0.5f)
                {
                    DCurvePoint d = new DCurvePoint(prevBinormal, 0, 0);
                    discretizedPoints.Add(d);
                    continue;
                }

                Vector3 curvatureBinormal = Vector3.Cross(previousVec, nextVec).normalized;
                if (i == 1)
                {
                    startingBinormal = curvatureBinormal;
                }

                // Compute bending angles (discrete curvature).
                float dot       = Vector3.Dot(previousVec, nextVec);
                float bendAngle = (dot >= 1) ? 0 : Mathf.Rad2Deg * Mathf.Acos(dot);

                // Compute twisting angles (discrete torsion).
                float twistAngle;
                // Compute twist angles as we go along.
                // The first vertex is considered to have no twist.
                if (i == 1)
                {
                    twistAngle = 0;
                }
                else
                {
                    twistAngle = TelescopeUtils.AngleBetween(prevBinormal, curvatureBinormal, previousVec);

                    // If the bend angle is tiny, then the curve is basically straight, so
                    // just set twist values to 0 to avoid unnecessary twisting.

                    /*if (Mathf.Abs(bendAngle) <= 0.1)
                     * {
                     *  bendAngle = 0;
                     *  twistAngle = 0;
                     * }*/
                }

                if (float.IsNaN(bendAngle))
                {
                    throw new System.Exception("Bend angle is nan, dot = " + dot);
                }
                if (float.IsNaN(twistAngle))
                {
                    throw new System.Exception("Twist angle is nan");
                }

                prevBinormal = curvatureBinormal;

                DCurvePoint dcp = new DCurvePoint(curvatureBinormal.normalized,
                                                  bendAngle, twistAngle);

                discretizedPoints.Add(dcp);
            }

            if (startingBinormal.magnitude < 0.001f)
            {
                if (startingTangent == Vector3.up)
                {
                    startingBinormal = Vector3.right;
                }
                else
                {
                    startingBinormal = Vector3.up;
                    Vector3 orthogonal = Vector3.Dot(startingBinormal, startingTangent) * startingTangent;
                    startingBinormal = startingBinormal - orthogonal;
                    startingBinormal.Normalize();
                }
            }

            targetEndPoint = ReconstructFromAngles();
            ComputeFrenetFrames();
            ComputeBishopFrames();
        }