// Use this for initialization
 void Start()
 {
     arcLength          = 0;
     measuredArc        = 0;
     transform.position = TelescopeUtils.TranslateAlongHelix(curvature, torsion, arcLength);
     transform.rotation = TelescopeUtils.RotateAlongHelix(curvature, torsion, arcLength);
 }
Example #2
0
        public void MakeShellsFromDiffs(List <TelescopeParameters> diffs)
        {
            initNumShells = diffs.Count;
            parameters    = diffs;
            shells        = new List <TelescopeShell>();
            initialDirection.Normalize();

            // Compute the absolute parameter values from the list of diffs we are given.
            List <TelescopeParameters> concreteParams = new List <TelescopeParameters>();
            TelescopeParameters        theParams      = diffs[0];

            concreteParams.Add(new TelescopeParameters(diffs[0]));
            for (int i = 1; i < initNumShells; i++)
            {
                if (diffs[i].radius > -wallThickness)
                {
                    diffs[i].radius = -wallThickness;
                }
                theParams         = theParams + diffs[i];
                theParams.length -= 0; // wallThickness;
                //theParams.radius -= wallThickness;
                concreteParams.Add(theParams);
            }

            // Make sure the final shell is greater than the minimum possible width.
            if (concreteParams[concreteParams.Count - 1].radius < wallThickness)
            {
                concreteParams[concreteParams.Count - 1].radius = wallThickness;
            }

            // Make sure that all the shells fit inside each other.
            TelescopeUtils.growChainToFit(concreteParams);

            MakeShellsFromFinalList(concreteParams);
        }
Example #3
0
        public TelescopeShell addChildShell(TelescopeShell parent,
                                            TelescopeParameters parentParams, TelescopeParameters childParams,
                                            TelescopeParameters nextParams, bool isNotLast)
        {
            int i = shells.Count;
            // Make the new shell, and set the previous shell as its parent
            GameObject shellObj = new GameObject();

            shellObj.transform.parent = parent.transform;
            shellObj.name             = name + "-shell" + i;

            // Make the geometry, etc.
            TelescopeShell newShell = shellObj.AddComponent <TelescopeShell>();

            newShell.GenerateGeometry(childParams, nextParams, doOverhang: true);
            newShell.setMaterial(material);

            // Set the shell's rest transformation relative to its parent.
            // When the shell's current extension ratio is 0, this is where
            // it is located relative to its parent.
            // newShell.baseRadians = newShell.radiansOfLength(wallThickness);
            newShell.baseTranslation = TelescopeUtils.childBasePosition(parentParams, childParams);
            newShell.baseRotation    = TelescopeUtils.childBaseRotation(parentParams, childParams);
            shells.Add(newShell);

            shellObj.layer = 8;

            newShell.containingSegment = this;

            return(newShell);
        }
Example #4
0
        CylinderMesh GenerateInnerCylinder(TelescopeParameters nextParams, bool overhang, float arcOffset,
                                           int extraRings = 0)
        {
            TelescopeParameters ourParams = getParameters();
            CylinderMesh        innerCyl;

            // If there is a change in profile from this shell to the next...
            if (nextParams != null && (nextParams.curvature != curvature || nextParams.torsion != torsion ||
                                       nextParams.radius < radius - Constants.WALL_THICKNESS * 1.01f))
            {
                // Generate the outer profile of the child shell; this will become
                // the inner profile of this shell.
                TelescopeParameters innerParams = new TelescopeParameters(nextParams.length, nextParams.radius,
                                                                          nextParams.thickness, nextParams.curvature, nextParams.torsion, nextParams.twistFromParent);
                innerCyl = GenerateCylinder(innerParams,
                                            Constants.TAPER_SLOPE, innerGroove: true, overhang: overhang,
                                            extraRings: extraRings);

                // Move and rotate the inner profile so that the end circles align.
                Quaternion alignRotation    = TelescopeUtils.childBaseRotation(ourParams, nextParams);
                Vector3    alignTranslation = TelescopeUtils.childBasePosition(ourParams, nextParams);

                Quaternion backRotation = TelescopeUtils.RotateAlongHelix(nextParams.curvature,
                                                                          nextParams.torsion, arcOffset);
                Vector3 backTranslation = TelescopeUtils.TranslateAlongHelix(nextParams.curvature,
                                                                             nextParams.torsion, arcOffset);

                innerCyl.ApplyRotation(backRotation);
                innerCyl.ApplyTranslation(backTranslation);

                innerCyl.ApplyRotation(alignRotation);
                innerCyl.ApplyTranslation(alignTranslation);
            }

            else
            {
                TelescopeParameters innerParams = new TelescopeParameters(length, radius - thickness,
                                                                          thickness, curvature, torsion, 0);

                innerCyl = GenerateCylinder(innerParams,
                                            Constants.TAPER_SLOPE, innerGroove: (nextParams != null), overhang: overhang,
                                            extraRings: extraRings);

                if (nextParams != null)
                {
                    Quaternion backRotation = TelescopeUtils.RotateAlongHelix(nextParams.curvature,
                                                                              nextParams.torsion, arcOffset);
                    Vector3 backTranslation = TelescopeUtils.TranslateAlongHelix(nextParams.curvature,
                                                                                 nextParams.torsion, arcOffset);

                    innerCyl.ApplyRotation(backRotation);
                    innerCyl.ApplyTranslation(backTranslation);
                }
            }

            return(innerCyl);
        }
        Vector3 TransformedHelixPoint(CurveSegment cs, float arcLen)
        {
            // Get the helix point in local coordinates
            Vector3 helixPoint = TelescopeUtils.TranslateAlongHelix(cs.curvature, cs.torsion, arcLen);
            // Transform to world
            Quaternion rotateToWorld = Quaternion.LookRotation(cs.frame.T, cs.frame.N);
            Vector3    world         = rotateToWorld * helixPoint + cs.startPosition;

            return(world);
        }
        Vector3 StartEndpointCC(float angleOffset)
        {
            Vector3 circumBegin = TelescopeUtils.Circumcenter(points[1], points[2], points[3]);
            Vector3 normalBegin = Vector3.Cross(points[2] - points[1], points[3] - points[1]);
            Vector3 beginOffset = points[1] - circumBegin;

            Vector3 rotatedBegin = Quaternion.AngleAxis(-angleOffset, normalBegin) * beginOffset + circumBegin;

            //Vector3 diffBegin = (rotatedBegin - points[1]).normalized * 0.1f;
            return(rotatedBegin);
        }
Example #7
0
        public void MakeShellsFromConcrete(List <TelescopeParameters> concreteParams)
        {
            initNumShells = concreteParams.Count;
            shells        = new List <TelescopeShell>();
            initialDirection.Normalize();

            // Make sure that all the shells fit inside each other.
            TelescopeUtils.growChainToFit(concreteParams);

            MakeShellsFromFinalList(concreteParams);
        }
        OrthonormalFrame TransformedHelixFrame(CurveSegment cs, float arcLen)
        {
            // Apply the local helix rotation.
            Quaternion oldRot = Quaternion.LookRotation(cs.frame.T, cs.frame.N);
            Quaternion newRot = oldRot *
                                TelescopeUtils.RotateAlongHelix(cs.curvature, cs.torsion, arcLen)
                                * Quaternion.Inverse(oldRot);
            OrthonormalFrame newFrame = cs.frame.RotatedBy(newRot);

            return(newFrame);
        }
 public void ShrinkToFit()
 {
     if (selected)
     {
         TelescopeSegment           segment   = selected.containingSegment;
         List <TelescopeParameters> allParams = segment.getParamList();
         TelescopeUtils.growChainToFit(allParams, shrinkFit: true);
         segment.MakeAllShells(allParams);
         segment.SetShellExtensions(1);
         selected = null;
     }
 }
        Vector3 EndEndpointCC(float angleOffset)
        {
            int     last      = points.Count - 1;
            Vector3 circumEnd = TelescopeUtils.Circumcenter(points[last - 1], points[last - 2], points[last - 3]);
            Vector3 normalEnd = Vector3.Cross(points[last - 2] - points[last - 1], points[last - 3] - points[last - 1]);
            Vector3 endOffset = points[last - 1] - circumEnd;

            Vector3 rotatedEnd = Quaternion.AngleAxis(-angleOffset, normalEnd) * endOffset + circumEnd;

            //Vector3 diffEnd = (rotatedEnd - points[last - 1]).normalized * 0.1f;
            return(rotatedEnd);
        }
        // Update is called once per frame
        void Update()
        {
            arcLength += Time.deltaTime;
            Vector3 pos  = TelescopeUtils.TranslateAlongHelix(curvature, torsion, arcLength);
            float   diff = Vector3.Distance(pos, transform.position);

            measuredArc       += diff;
            transform.position = pos;
            transform.rotation = TelescopeUtils.RotateAlongHelix(curvature, torsion, arcLength);

            velocity = diff / Time.deltaTime;
        }
Example #12
0
        float AverageCurvature()
        {
            // Get the average curvature of this curve
            float averageCurvature = 0;

            foreach (DCurvePoint dcp in discretizedPoints)
            {
                averageCurvature += dcp.bendingAngle * Mathf.Deg2Rad;
            }
            averageCurvature /= discretizedPoints.Count;
            averageCurvature  = TelescopeUtils.CurvatureOfDiscrete(averageCurvature, segmentLength);
            return(averageCurvature);
        }
Example #13
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 #14
0
 public static void growChainToFit(List <TelescopeParameters> parameters, bool shrinkFit = false)
 {
     // Make a pass in reverse that grows each parent so that it is large enough
     // to contain its child.
     for (int i = parameters.Count - 1; i > 0; i--)
     {
         if (parameters[i - 1].torsion != 0 || parameters[i].torsion != 0)
         {
             TelescopeUtils.growParentToChildHelix(parameters[i - 1], parameters[i], shrinkFit);
         }
         else
         {
             TelescopeUtils.growParentToChild(parameters[i - 1], parameters[i], shrinkFit);
         }
     }
 }
Example #15
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 #16
0
 public Quaternion rotationOfDistance(float arcLength, float curvature, float torsion)
 {
     return(TelescopeUtils.RotateAlongHelix(curvature, torsion, arcLength));
 }
Example #17
0
 Vector3 translationOfDistance(float arcLength, float curvature, float torsion)
 {
     return(TelescopeUtils.TranslateAlongHelix(curvature, torsion, arcLength));
 }
Example #18
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();
        }
Example #19
0
        // Update is called once per frame
        void Update()
        {
            if (ReversedOption != Reversed)
            {
                ReverseTelescope();
                Reversed = ReversedOption;
            }

            if (Input.GetKeyDown("["))
            {
                List <Vector3> pts = new List <Vector3>();
                pts.Add(BasePointAtCenter);
                pts.Add(BasePointOnSurface);
                TelescopeUtils.DisplayLine(pts);
            }

            /*
             * if (Input.GetKey("left shift") && Input.GetKeyDown("enter"))
             * {
             *  ExtendImmediate(0);
             *
             *  STLWriter.WriteSTLOfSegment(this, WorldSpaceMin - new Vector3(0.01f, 0.01f, 0.01f), name + ".stl");
             *
             *  Mesh volume = shells[0].GenerateInnerVolume(shells[1].getParameters(), -0.5f);
             *  GameObject innerVolume = new GameObject();
             *  MeshFilter mf = innerVolume.AddComponent<MeshFilter>();
             *  innerVolume.AddComponent<MeshRenderer>().material = DesignerController.instance.defaultTelescopeMaterial;
             *  mf.mesh = volume;
             *
             *  innerVolume.transform.parent = shells[0].transform;
             *  innerVolume.transform.localPosition = Vector3.zero;
             *  innerVolume.transform.localRotation = Quaternion.identity;
             *
             *  //shells[0].ReplaceMesh(volume);
             *
             *  for (int i = 1; i < shells.Count; i++)
             *  {
             *      shells[i].GetComponent<MeshRenderer>().enabled = false;
             *  }
             *
             *  //STLWriter.WriteSTLOfMesh(shells[0].mesh, "scad/innerVolume.stl");
             * }
             */

            if (rootSegment)
            {
                if (Input.GetKeyDown("e"))
                {
                    ExtendTo(1, Mathf.Log(shells.Count));
                }
                else if (Input.GetKeyDown("q"))
                {
                    ExtendTo(0, Mathf.Log(shells.Count));
                }
            }

            if (currentlyInterp)
            {
                extensionTime   += Time.deltaTime;
                currentExtension = Mathf.Lerp(oldExtension, targetExtension, extensionTime / extensionTimespan);
                if (extensionTime >= extensionTimespan)
                {
                    currentlyInterp  = false;
                    currentExtension = targetExtension;
                }
                SetShellExtensions(currentExtension);
            }

            for (int i = 1; i < shells.Count; i++)
            {
                shells[i].SetTransform();
            }

            if (Input.GetKeyDown("/"))
            {
                List <Vector3> firstRing = FirstVertRing;
                List <Vector3> lastRing  = LastVertRing;

                foreach (Vector3 v in firstRing)
                {
                    GameObject g = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                    g.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
                    g.transform.position   = v;
                }

                foreach (Vector3 v in lastRing)
                {
                    GameObject g = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                    g.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
                    g.transform.position   = v;
                }
            }
        }