Beispiel #1
0
        public void PrependShell()
        {
            Vector3    loc = shells[0].getLocalLocationAlongPath(-1);
            Quaternion rot = shells[0].getLocalRotationAlongPath(-1);

            TelescopeParameters p = new TelescopeParameters(shells[0].getParameters());

            p.radius += p.thickness;

            // Create the new shell object
            GameObject     newShell = new GameObject();
            TelescopeShell shell    = newShell.AddComponent <TelescopeShell>();

            shell.GenerateGeometry(p, null);
            shell.setMaterial(material);

            Vector3    shellLoc = shells[0].transform.position;
            Quaternion shellRot = shells[0].transform.rotation;

            // Move the new shell to be in position to receive the old one
            shell.transform.parent   = shells[0].transform.parent;
            shell.transform.position = shellLoc + shellRot * loc;
            shell.transform.rotation = shellRot * rot;

            // Reparent the old starting shell so it becomes the child of the new one
            shells[0].baseTranslation  = Vector3.zero;
            shells[0].baseRotation     = Quaternion.identity;
            shells[0].transform.parent = shell.transform;
            shell.extensionRatio       = shells[0].extensionRatio;
            shells.Insert(0, shell);
        }
Beispiel #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);
        }
Beispiel #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);
        }
Beispiel #4
0
 public TelescopeParameters(TelescopeParameters baseParams, TelescopeParameters diff)
 {
     length          = baseParams.length + diff.length;
     radius          = baseParams.radius + diff.radius;
     thickness       = baseParams.thickness;
     curvature       = baseParams.curvature + diff.curvature;
     torsion         = baseParams.torsion + diff.torsion;
     twistFromParent = diff.twistFromParent;
 }
Beispiel #5
0
 public TelescopeParameters(TelescopeParameters toCopy)
 {
     length          = toCopy.length;
     radius          = toCopy.radius;
     thickness       = toCopy.thickness;
     curvature       = toCopy.curvature;
     torsion         = toCopy.torsion;
     twistFromParent = toCopy.twistFromParent;
 }
Beispiel #6
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);
        }
Beispiel #7
0
        public static void growParentToChildHelix(TelescopeParameters parent, TelescopeParameters child, bool shrinkFit = false)
        {
            float maxRequiredRadius = 0;

            // Find the largest radius necessary at every point along the parent arc
            for (int i = 0; i <= Constants.CUTS_PER_CYLINDER; i++)
            {
                float   arcPos    = parent.length / Constants.CUTS_PER_CYLINDER * i;
                Vector3 parentPos = TranslateAlongHelix(parent.curvature, parent.torsion, arcPos);
                Vector3 parentT   = FrameAlongHelix(parent.curvature, parent.torsion, arcPos).T;

                float   minDot       = 1;
                Vector3 closestPoint = parentPos;
                float   closestArc   = 0;

                // Find the point on the second arc nearest to the normal of the first one.
                for (int j = 0; j <= Constants.CUTS_PER_CYLINDER; j++)
                {
                    float   childArc    = child.length / Constants.CUTS_PER_CYLINDER * j;
                    Vector3 childPos    = TranslateAlongHelix(child.curvature, child.torsion, childArc);
                    Vector3 childOffset = childPos - parentPos;

                    // Want the point to be in the orthogonal plane of the tangent, since
                    // the cross-sections of the shell are circular in that plane
                    float dot = Vector3.Dot(childOffset.normalized, parentT.normalized);

                    if (Mathf.Abs(dot) < minDot)
                    {
                        minDot       = Mathf.Abs(dot);
                        closestPoint = childPos;
                        closestArc   = childArc;
                    }
                }

                // Don't count the change if the dot product is too large, because this probably means
                // we went past the end of the arc segment.
                if (minDot > 0.3f)
                {
                    continue;
                }

                // Write out the parameters for the circle in the child shell
                Vector3 closestTangent = FrameAlongHelix(child.curvature, child.torsion, closestArc).T;
                // Get the farthest point on the outside of the child shell
                Vector3 farthest       = FarthestPointOnCircle(closestPoint, closestTangent, child.radius, parentPos);
                float   requiredRadius = Vector3.Distance(farthest, parentPos);

                maxRequiredRadius = Mathf.Max(requiredRadius, maxRequiredRadius);
            }
            // Account for wall thickness
            maxRequiredRadius += Constants.WALL_THICKNESS;

            // Widen the parent so it contains the child shell.
            // However, don't ever decrease the thickness.
            parent.radius = Mathf.Max(parent.radius, maxRequiredRadius);
        }
Beispiel #8
0
        /// <summary>
        /// Returns the local rotation of a child shell with the given parameters,
        /// such that, when used with the local position from childBasePosition,
        /// the end cross-section of the child will be perfectly aligned
        /// with the end cross-section of the parent with its parameters.
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="child"></param>
        /// <param name="useTorsion"></param>
        /// <returns></returns>
        public static Quaternion childBaseRotation(TelescopeParameters parent,
                                                   TelescopeParameters child, bool useTorsion = true)
        {
            float      parentTorsion  = (useTorsion) ? parent.torsion : 0;
            float      childTorsion   = (useTorsion) ? child.torsion : 0;
            Quaternion rotationToBase = RotateAlongHelix(parent.curvature, parentTorsion, parent.length);
            Quaternion rotationBack   = RotateAlongHelix(child.curvature, childTorsion, -child.length);

            return(rotationToBase * rotationBack);
        }
Beispiel #9
0
        /// <summary>
        /// Returns the local position of a child shell with the given parameters,
        /// such that (when combined with the local rotation from childBaseRotation)
        /// the end cross-section of the child will be perfectly aligned
        /// with the end cross-section of the parent with its parameters.
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="child"></param>
        /// <param name="useTorsion"></param>
        /// <returns></returns>
        public static Vector3 childBasePosition(TelescopeParameters parent,
                                                TelescopeParameters child, bool useTorsion = true)
        {
            float      parentTorsion        = (useTorsion) ? parent.torsion : 0;
            float      childTorsion         = (useTorsion) ? child.torsion : 0;
            Vector3    translationToBase    = TranslateAlongHelix(parent.curvature, parentTorsion, parent.length);
            Quaternion rotationToBase       = RotateAlongHelix(parent.curvature, parentTorsion, parent.length);
            Vector3    translationBackwards = TranslateAlongHelix(child.curvature, childTorsion, -child.length);

            translationToBase = translationToBase + (rotationToBase * translationBackwards);
            return(translationToBase);
        }
Beispiel #10
0
        public static void growParentToChild(TelescopeParameters parent, TelescopeParameters child, bool shrinkFit = false)
        {
            // Compute the coordinates of the child's starting position,
            // in the parent's coordinate frame.
            Vector3    childBasePos = childBasePosition(parent, child);
            Quaternion childBaseRot = childBaseRotation(parent, child);

            Vector3 childOutward = childBaseRot * Vector3.down;

            // Compute the two inner corners of the child, when nested inside its
            // parent; these are the corners we want to bounds check.
            Vector3 retractedInner = childBasePos - (child.radius * childOutward);
            Vector3 retractedOuter = childBasePos + (child.radius * childOutward);

            // If the parent has no curvature, then the required width is just the
            // max absolute y value of the child.
            float finalRadius;

            if (parent.curvature < 1e-6)
            {
                finalRadius = Mathf.Max(Mathf.Abs(retractedInner.y), Mathf.Abs(retractedOuter.y)) + parent.thickness;
                if (!shrinkFit)
                {
                    finalRadius = Mathf.Max(finalRadius, parent.radius);
                }
            }

            // Otherwise we need to compute the distance from the center line to the
            // corners, and take their max distance.
            else
            {
                // Fact: The centers of rotation for the parent and the extended child both lie
                // on the line (in the ZY plane) defined by the parent's center and its far face.
                float   parentRadius     = 1f / parent.curvature;
                Vector3 centerOfRotation = new Vector3(0, parentRadius, 0);

                // Now we can determine what width we need to 'fatten' the parent by.
                float innerDistance = Vector3.Distance(retractedInner, centerOfRotation);
                float outerDistance = Vector3.Distance(retractedOuter, centerOfRotation);
                float innerDiff     = Mathf.Abs(innerDistance - parentRadius);
                float outerDiff     = Mathf.Abs(outerDistance - parentRadius);

                finalRadius = Mathf.Max(innerDiff, outerDiff) + parent.thickness;
                if (!shrinkFit)
                {
                    finalRadius = Mathf.Max(finalRadius, parent.radius);
                }
            }

            parent.radius = finalRadius;
            // parent.thickness += widthChange;
        }
Beispiel #11
0
        CylinderMesh GenerateCylinder(TelescopeParameters tParams, float slope,
                                      bool innerGroove = false, bool outerGroove = false, bool overhang = true,
                                      int extraRings   = 0)
        {
            // We basically need to sweep a circular cross-section along a circular path.
            List <List <IndexedVertex> > circles = new List <List <IndexedVertex> >();

            float lengthStep = 1f / (Constants.CUTS_PER_CYLINDER - 1);

            float radiusLoss = 0;

            int numCircles = Constants.CUTS_PER_CYLINDER + (overhang ? Constants.OVERHANG_CUTS : 0) + extraRings;

            // Generate vertices
            for (int i = 0; i < numCircles; i++)
            {
                radiusLoss = i * lengthStep * slope * tParams.length;
                Vector3 centerPoint     = getLocalLocationAlongPath(i * lengthStep, tParams.curvature, tParams.torsion);
                Vector3 facingDirection = getDirectionAlongPath(i * lengthStep, tParams.curvature, tParams.torsion);
                Vector3 normalDirection = getNormalAlongPath(i * lengthStep, tParams.curvature, tParams.torsion);

                bool doInner = (innerGroove && i < Constants.CUTS_PER_CYLINDER + Constants.FIN_CUTS);
                bool doOuter = (outerGroove && i <= Constants.FIN_CUTS);

                List <IndexedVertex> circle = GenerateCircle(i, centerPoint, facingDirection, normalDirection,
                                                             tParams.radius - radiusLoss, addInnerGrooves: doInner, addOuterGroove: doOuter);
                circles.Add(circle);
            }

            // Now generate faces
            List <IndexTriangle> allIndices = new List <IndexTriangle>();

            for (int i = 0; i < numCircles - 1; i++)
            {
                List <IndexTriangle> tris = StitchCircles(circles[i], circles[i + 1]);
                allIndices.AddRange(tris);
            }

            CylinderMesh cm = new CylinderMesh(circles, allIndices);

            return(cm);
        }
        public void SelectShell(TelescopeShell selection)
        {
            if (!selection)
            {
                return;
            }
            if (selected)
            {
                selected.setMaterial(defaultTelescopeMaterial);
            }
            selected = selection;
            selected.setMaterial(selectedTelescopeMaterial);

            TelescopeParameters tp = selected.getParameters();

            lengthField.text    = tp.length.ToString();
            radiusField.text    = tp.radius.ToString();
            curvatureField.text = tp.curvature.ToString();
            twistField.text     = tp.twistFromParent.ToString();
        }
Beispiel #13
0
        public Mesh GenerateInnerVolume(TelescopeParameters nextParams, float arcOffset, int extraRings = 0)
        {
            currentIndex = 0;

            Mesh mesh = new Mesh();

            // Get the inner cylinder of the shell
            CylinderMesh inner = GenerateInnerCylinder(nextParams, HasOverhang, arcOffset, extraRings: extraRings);

            // Get the vertices
            List <IndexedVertex> verticesList = flattenList(inner.circleCuts);
            // Create the triangles for the two ends of the cylinder; this also
            // adds 2 vertices to the list.
            List <IndexTriangle> capTris = CloseCylinderCaps(inner, verticesList);
            // Get the positions out of the list
            List <Vector3> vertices = verticesList.ConvertAll(new
                                                              System.Converter <IndexedVertex, Vector3>(IndexedVertex.toVector3));
            List <int> indicesList = new List <int>();

            // Add triangles for the cylinder itself
            foreach (IndexTriangle tri in inner.triangles)
            {
                tri.addFrontFace(indicesList);
            }

            // Add triangles for the two ends
            foreach (IndexTriangle tri in capTris)
            {
                tri.addFrontFace(indicesList);
            }

            mesh.vertices  = vertices.ToArray();
            mesh.triangles = indicesList.ToArray();
            mesh.RecalculateNormals();
            mesh.RecalculateBounds();

            return(mesh);
        }
        TelescopeSegment CreateStraightSegment(float length, float radius)
        {
            GameObject       segObj = new GameObject();
            TelescopeSegment seg    = segObj.AddComponent <TelescopeSegment>();

            List <TelescopeParameters> paramList = new List <TelescopeParameters>();
            float thickness   = Constants.WALL_THICKNESS;
            float startRadius = radius + 3 * thickness + 3 * length * Constants.TAPER_SLOPE;

            TelescopeParameters firstParam = new TelescopeParameters(length,
                                                                     startRadius, thickness, 0, 0, 0);

            paramList.Add(firstParam);

            paramList.Add(new TelescopeParameters(0, 0, 0, 0, 0, 0));
            paramList.Add(new TelescopeParameters(0, 0, 0, 0, 0, 0));

            seg.material = segment1.material;
            seg.MakeShellsFromDiffs(paramList);
            seg.transform.parent = transform;

            return(seg);
        }
Beispiel #15
0
        public TelescopeParameters getParameters()
        {
            TelescopeParameters tp = new TelescopeParameters(length, radius, thickness, curvature, torsion, twistAngle);

            return(tp);
        }
Beispiel #16
0
        public void GenerateGeometry(TelescopeParameters theParams, TelescopeParameters nextParams,
                                     bool doOverhang = true, bool outerGroove = true)
        {
            HasOverhang = doOverhang;

            this.thickness      = theParams.thickness;
            this.length         = theParams.length;
            this.radius         = theParams.radius;
            this.curvature      = theParams.curvature;
            this.torsion        = theParams.torsion;
            this.twistAngle     = theParams.twistFromParent;
            this.nextTwistAngle = (nextParams != null) ? nextParams.twistFromParent : 0;

            // Reset the mesh.
            currentIndex = 0;
            mFilter.mesh.Clear();

            float slopeCosmetic = thickness * Constants.COSMETIC_TAPER_RATIO;

            TelescopeParameters outerParams = new TelescopeParameters(length, radius - Constants.SHELL_GAP,
                                                                      thickness, curvature, torsion, 0);

            CylinderMesh outerCyl = GenerateCylinder(outerParams,
                                                     slopeCosmetic + Constants.TAPER_SLOPE,
                                                     outerGroove: outerGroove, overhang: doOverhang);

            CylinderMesh innerCyl = GenerateInnerCylinder(nextParams, doOverhang, 0);

            // Flatten vertex list
            List <IndexedVertex> outerVerts = flattenList(outerCyl.circleCuts);
            List <IndexedVertex> innerVerts = flattenList(innerCyl.circleCuts);

            outerVerts.AddRange(innerVerts);

            // Get the triangles that join the inner and outer surfaces.
            List <IndexTriangle> edgeTriangles = stitchCylinderEnds(outerCyl, innerCyl);

            // Sort the vertices just to be safe
            outerVerts.Sort();

            // Make vertex buffer
            List <Vector3> vecs = outerVerts.ConvertAll(new System.Converter <IndexedVertex, Vector3>(IndexedVertex.toVector3));

            Vector3[] vertices = vecs.ToArray();

            // Make index buffer
            List <int> indicesList = new List <int>();

            foreach (IndexTriangle tri in outerCyl.triangles)
            {
                tri.addFrontFace(indicesList);
            }
            foreach (IndexTriangle tri in innerCyl.triangles)
            {
                tri.addBackFace(indicesList);
            }
            foreach (IndexTriangle tri in edgeTriangles)
            {
                tri.addFrontFace(indicesList);
            }

            mFilter.mesh.vertices  = vertices;
            mFilter.mesh.triangles = indicesList.ToArray();

            mFilter.mesh.RecalculateBounds();
            mFilter.mesh.RecalculateNormals();
        }
Beispiel #17
0
        public static TelescopeParameters operator +(TelescopeParameters t1, TelescopeParameters t2)
        {
            TelescopeParameters sum = new TelescopeParameters(t1, t2);

            return(sum);
        }
Beispiel #18
0
        public static TelescopeSegment telescopeOfCone(Vector3 startPos, float startRadius,
                                                       Vector3 endPos, float endRadius, Vector3 curvatureCenter,
                                                       float wallThickness = Constants.WALL_THICKNESS,
                                                       bool useCurvature   = false)
        {
            float   curvature;
            Vector3 segmentDirection;

            if (useCurvature)
            {
                float radius = Vector3.Distance(curvatureCenter, startPos);
                curvature = 1f / radius;
                if (curvature < 1e-6)
                {
                    curvature        = 0;
                    segmentDirection = endPos - startPos;
                    segmentDirection.Normalize();
                }
                else
                {
                    segmentDirection = CurveDirectionFromParent(startPos, endPos, curvatureCenter);
                }
            }
            else
            {
                curvature        = 0;
                segmentDirection = endPos - startPos;
                segmentDirection.Normalize();
            }

            float distance = ArcLengthFromChord(startPos, endPos, curvature);

            int numShells = Mathf.CeilToInt((Mathf.Max(startRadius, endRadius) -
                                             Mathf.Min(startRadius, endRadius)) / wallThickness);

            if (numShells < 2)
            {
                numShells = 2;
            }

            // int numShells = Mathf.CeilToInt(distance / Mathf.Min(startRadius, endRadius));

            // Length is just the distance we need to cover divided by the number of shells.
            float lengthPerShell = distance / numShells;
            // We attempt to choose the radii such that the telescope tapers from the start
            // radius to the end radius over the given number of shells.
            float radiusStep = (startRadius - endRadius) / numShells;

            float twist = 0;

            if (curvature >= 1e-6)
            {
                // Compute twist angles
                Quaternion rotationToOrigin = Quaternion.FromToRotation(Vector3.forward, segmentDirection);
                // The "up" direction we would like to have -- orthogonal direction from circle center.
                Vector3 startEnd  = endPos - startPos;
                Vector3 desiredUp = startEnd - Vector3.Dot(segmentDirection, startEnd) * segmentDirection;
                desiredUp.Normalize();
                Vector3 inverseDesired = Quaternion.Inverse(rotationToOrigin) * desiredUp;

                // The angle computation doesn't work right in 3rd and 4th quadrants,
                // so work around it by doing everything in 1st and 2nd.
                if (inverseDesired.x < 0)
                {
                    inverseDesired *= -1;
                    twist           = 180;
                }

                float angleBetween = Mathf.Atan2(Vector3.Cross(Vector3.up, inverseDesired).magnitude,
                                                 Vector3.Dot(Vector3.up, inverseDesired));

                twist += -angleBetween * Mathf.Rad2Deg;
            }

            List <TelescopeParameters> diffList = new List <TelescopeParameters>();

            // Create the initial shell parameters.
            TelescopeParameters initialParams = new TelescopeParameters(lengthPerShell, startRadius, wallThickness, curvature, 0, twist);

            diffList.Add(initialParams);
            // Create all the diffs.
            for (int i = 1; i < numShells; i++)
            {
                TelescopeParameters tp = new TelescopeParameters(0, -radiusStep, wallThickness, 0, 0, 0);
                diffList.Add(tp);
            }

            // Create a game object that will be the new segment.
            GameObject obj = new GameObject();

            obj.name = "segment" + segmentCount;
            segmentCount++;
            obj.transform.position = startPos;
            TelescopeSegment seg = obj.AddComponent <TelescopeSegment>();

            seg.material         = DesignerController.instance.defaultTelescopeMaterial;
            seg.initialDirection = segmentDirection;

            seg.MakeShellsFromDiffs(diffList);
            seg.transform.position = startPos;

            return(seg);
        }
Beispiel #19
0
 public static TelescopeParameters shrinkChildToParent(TelescopeParameters parent, TelescopeParameters child)
 {
     Debug.Log("Unimplemented");
     return(child);
 }
        public TelescopeSegment MakeTelescope(float startRadius, bool reverse = false)
        {
            List <TelescopeParameters> tParams = new List <TelescopeParameters>();

            CurveSegment initialSeg = (reverse) ? segments[segments.Count - 1] : segments[0];

            float wallThickness = Constants.WALL_THICKNESS;
            float currRadius    = startRadius * BulbShrinkRatio;

            TelescopeParameters initial = new TelescopeParameters(initialSeg.arcLength, currRadius,
                                                                  Constants.WALL_THICKNESS, initialSeg.curvature, initialSeg.torsion, 0);

            tParams.Add(initial);

            for (int i = 1; i < segments.Count; i++)
            {
                int index = (reverse) ? segments.Count - 1 - i : i;

                /*
                 * if (i == 2 && StartJuncture && StartJuncture.childCurves.Count == 5)
                 * {
                 *  Debug.Log("Hack to create lizard toenails, please delete once done");
                 *  currRadius -= 1.5f * wallThickness;
                 * }*/

                // Subtract the wall thickness of the previous piece
                currRadius -= wallThickness;

                float curvature = (reverse) ? segments[index].curvature : segments[index].curvature;
                float torsion   = (reverse) ? segments[index].torsion : segments[index].torsion;
                float impulse   = (reverse) ? -segments[index + 1].impulse : -segments[index].impulse;
                impulse *= Mathf.Rad2Deg;

                TelescopeParameters p = new TelescopeParameters(segments[index].arcLength, currRadius,
                                                                wallThickness, curvature, torsion, impulse);
                tParams.Add(p);
            }

            GameObject obj = new GameObject();

            obj.name = "telescope" + (numScopes++);

            TelescopeSegment segment = obj.AddComponent <TelescopeSegment>();

            segment.paramMode = SegmentParametersMode.Concrete;
            segment.material  = DesignerController.instance.defaultTelescopeMaterial;

            if (reverse)
            {
                CurveSegment lastSeg = segments[segments.Count - 1];
                obj.transform.position = TransformedHelixPoint(lastSeg, lastSeg.arcLength);

                OrthonormalFrame initFrame = TransformedHelixFrame(lastSeg, lastSeg.arcLength);
                segment.initialDirection = -initFrame.T;
                segment.initialUp        = initFrame.N;
            }
            else
            {
                obj.transform.position   = segments[0].startPosition;
                segment.initialDirection = segments[0].frame.T;
                segment.initialUp        = segments[0].frame.N;
            }

            segment.MakeShellsFromConcrete(tParams);

            if (reverse)
            {
                segment.ReverseTelescope();
            }

            return(segment);
        }
Beispiel #21
0
        public void MakeAllShells(List <TelescopeParameters> paramList, bool reversed = false)
        {
            DeleteTelescope();

            // Create an object for the first shell
            GameObject rootShellObj = new GameObject();

            rootShellObj.name                    = name + "-shell0";
            rootShellObj.transform.parent        = this.transform;
            rootShellObj.transform.localPosition = Vector3.zero;

            telescopeRootShell = rootShellObj;

            // Make the shell geometry
            TelescopeShell shell = rootShellObj.AddComponent <TelescopeShell>();
            // Get the twist impulse of the shell after, since we need to cut the
            // grooves in this shell to enable it
            TelescopeParameters params1 = (paramList.Count > 1) ? paramList[1] : null;

            shell.GenerateGeometry(paramList[0], params1, outerGroove: false);
            shell.setMaterial(material);

            // Shells don't know anything about their position/rotation,
            // so we set that here.
            Quaternion initialFacing = Quaternion.LookRotation(initialDirection, initialUp);

            rootShellObj.transform.rotation = initialFacing;
            rootShellObj.layer = 8;

            shell.containingSegment = this;

            // shell.baseRadians = 0;
            shell.baseTranslation = Vector3.zero;
            shell.baseRotation    = Quaternion.identity;

            shells.Add(shell);
            shell.isRoot = true;

            // Make all of the child shells here.
            TelescopeShell      prevShell      = shell;
            TelescopeParameters previousParams = paramList[0];
            TelescopeParameters currentParams  = paramList[0];

            float accumulatedTaper = shell.getTaperLoss();

            for (int i = 1; i < paramList.Count; i++)
            {
                // Get the computed parameters for this and the previous shell.
                currentParams  = paramList[i];
                previousParams = paramList[i - 1];

                // Shrink the radius by the accumulated taper so far.
                currentParams.radius -= accumulatedTaper;

                // Get the twist impulse for the next shell, so that we can cut the grooves.
                TelescopeParameters nextParams = (i < paramList.Count - 1) ? paramList[i + 1] : null;

                TelescopeParameters taperedParams = (nextParams != null) ? new TelescopeParameters(nextParams) : null;
                if (taperedParams != null)
                {
                    taperedParams.radius -= accumulatedTaper;
                }

                // Add it.
                bool isNotLast = (i < paramList.Count - 1);
                prevShell         = addChildShell(prevShell, previousParams, currentParams, taperedParams, isNotLast);
                accumulatedTaper += prevShell.getTaperLoss();
            }


            if (fountainPrefab)
            {
                GameObject fountain = Instantiate <GameObject>(fountainPrefab);
                fountain.transform.parent = prevShell.transform;
            }
        }