Пример #1
0
        private static Path GeneratePathPolygon(LLObject.ObjectData prim, int sides, float startOff, float endScale,
            float twistScale)
        {
            Path path = new Path();
            path.Points = new List<PathPoint>();

            float revolutions = prim.PathRevolutions;
            float skew = prim.PathSkew;
            float skewMag = (float)Math.Abs(skew);
            float holeX = prim.PathScaleX * (1f - skewMag);
            float holeY = prim.PathScaleY;

            // Calculate taper begin/end for x,y (Negative means taper the beginning)
            float taperXBegin = 1f;
            float taperXEnd = 1f - prim.PathTaperX;
            float taperYBegin = 1f;
            float taperYEnd = 1f - prim.PathTaperY;

            if (taperXEnd > 1f)
            {
                // Flip tapering
                taperXBegin = 2f - taperXEnd;
                taperXEnd = 1f;
            }
            if (taperYEnd > 1f)
            {
                // Flip tapering
                taperYBegin = 2f - taperYEnd;
                taperYEnd = 1f;
            }

            // For spheres, the radius is usually zero
            float radiusStart = 0.5f;
            if (sides < 8)
                radiusStart = TABLE_SCALE[sides];

            // Scale the radius to take the hole size into account
            radiusStart *= 1f - holeY;

            // Now check the radius offset to calculate the start,end radius. (Negative means
            // decrease the start radius instead)
            float radiusEnd = radiusStart;
            float radiusOffset = prim.PathRadiusOffset;
            if (radiusOffset < 0f)
                radiusStart *= 1f + radiusOffset;
            else
                radiusEnd *= 1f - radiusOffset;

            // Is the path NOT a closed loop?
            path.Open =
                ((prim.PathEnd * endScale - prim.PathBegin < 1f) ||
                (skewMag > 0.001f) ||
                (Math.Abs(taperXEnd - taperXBegin) > 0.001d) ||
                (Math.Abs(taperYEnd - taperYBegin) > 0.001d) ||
                (Math.Abs(radiusEnd - radiusStart) > 0.001d));

            float ang, c, s;
            Quaternion twist = Quaternion.Identity;
            Quaternion qang = Quaternion.Identity;
            PathPoint point;
            Vector3 pathAxis = new Vector3(1f, 0f, 0f);
            float twistBegin = prim.PathTwistBegin * twistScale;
            float twistEnd = prim.PathTwist * twistScale;

            // We run through this once before the main loop, to make sure
            // the path begins at the correct cut
            float step = 1f / sides;
            float t = prim.PathBegin;
            ang = 2f * F_PI * revolutions * t;
            s = (float)Math.Sin(ang) * MathHelper.Lerp(radiusStart, radiusEnd, t);
            c = (float)Math.Cos(ang) * MathHelper.Lerp(radiusStart, radiusEnd, t);

            point = new PathPoint();
            point.Position = new Vector3(
                0 + MathHelper.Lerp(0, prim.PathShearX, s) +
                0 + MathHelper.Lerp(-skew, skew, t) * 0.5f,
                c + MathHelper.Lerp(0, prim.PathShearY, s),
                s);
            point.Scale.X = holeX * MathHelper.Lerp(taperXBegin, taperXEnd, t);
            point.Scale.Y = holeY * MathHelper.Lerp(taperYBegin, taperYEnd, t);
            point.TexT = t;

            // Twist rotates the path along the x,y plane
            twist = Quaternion.CreateFromAxisAngle(MathHelper.Lerp(twistBegin, twistEnd, t) * 2f * F_PI - F_PI, 0f, 0f, 1f);
            // Rotate the point around the circle's center
            qang = Quaternion.CreateFromAxisAngle(pathAxis, ang);
            point.Rotation = twist * qang;

            path.Points.Add(point);
            t += step;

            // Snap to a quantized parameter, so that cut does not
            // affect most sample points
            t = ((int)(t * sides)) / (float)sides;

            // Run through the non-cut dependent points
            point = new PathPoint();
            while (t < prim.PathEnd)
            {
                ang = 2f * F_PI * revolutions * t;
                c = (float)Math.Cos(ang) * MathHelper.Lerp(radiusStart, radiusEnd, t);
                s = (float)Math.Sin(ang) * MathHelper.Lerp(radiusStart, radiusEnd, t);

                point.Position = new Vector3(
                    0 + MathHelper.Lerp(0, prim.PathShearX, s) +
                    0 + MathHelper.Lerp(-skew, skew, t) * 0.5f,
                    c + MathHelper.Lerp(0, prim.PathShearY, s),
                    s);

                point.Scale.X = holeX * MathHelper.Lerp(taperXBegin, taperXEnd, t);
                point.Scale.Y = holeY * MathHelper.Lerp(taperYBegin, taperYEnd, t);
                point.TexT = t;

                // Twist rotates the path along the x,y plane
                twist = Quaternion.CreateFromAxisAngle(MathHelper.Lerp(twistBegin, twistEnd, t) * 2f * F_PI - F_PI, 0f, 0f, 1f);
                // Rotate the point around the circle's center
                qang = Quaternion.CreateFromAxisAngle(pathAxis, ang);
                point.Rotation = twist * qang;

                path.Points.Add(point);
                t += step;
            }

            // Make one final pass for the end cut
            t = prim.PathEnd;
            point = new PathPoint();
            ang = 2f * F_PI * revolutions * t;
            c = (float)Math.Cos(ang) * MathHelper.Lerp(radiusStart, radiusEnd, t);
            s = (float)Math.Sin(ang) * MathHelper.Lerp(radiusStart, radiusEnd, t);

            point.Position = new Vector3(
                MathHelper.Lerp(0, prim.PathShearX, s) + MathHelper.Lerp(-skew, skew, t) * 0.5f,
                c + MathHelper.Lerp(0, prim.PathShearY, s),
                s);
            point.Scale.X = holeX * MathHelper.Lerp(taperXBegin, taperXEnd, t);
            point.Scale.Y = holeY * MathHelper.Lerp(taperYBegin, taperYEnd, t);
            point.TexT = t;

            // Twist rotates the path along the x,y plane
            twist = Quaternion.CreateFromAxisAngle(MathHelper.Lerp(twistBegin, twistEnd, t) * 2f * F_PI - F_PI, 0f, 0f, 1f);
            qang = Quaternion.CreateFromAxisAngle(pathAxis, ang);
            point.Rotation = twist * qang;

            path.Points.Add(point);

            return path;
        }
Пример #2
0
        private static Path GeneratePath(LLObject.ObjectData prim, float detail)
        {
            Path path;
            path.Open = true;
            int np = 2; // Hardcode for line
            float step;

            switch (prim.PathCurve)
            {
                default:
                case LLObject.PathCurve.Line:
                    {
                        // Take the begin/end twist into account for detail
                        np = (int)Math.Floor(Math.Abs(prim.PathTwistBegin - prim.PathTwist) * 3.5f * (detail - 0.5f)) + 2;
                        path.Points = new List<PathPoint>(np);

                        step = 1f / (np - 1);

                        Vector2 startScale = prim.PathBeginScale;
                        Vector2 endScale = prim.PathEndScale;

                        for (int i = 0; i < np; i++)
                        {
                            PathPoint point = new PathPoint();

                            float t = MathHelper.Lerp(prim.PathBegin, prim.PathEnd, (float)i * step);
                            point.Position = new Vector3(
                                MathHelper.Lerp(0, prim.PathShearX, t),
                                MathHelper.Lerp(0, prim.PathShearY, t),
                                t - 0.5f);
                            point.Rotation = Quaternion.CreateFromAxisAngle(MathHelper.Lerp(F_PI * prim.PathTwistBegin, F_PI * prim.PathTwist, t), 0f, 0f, 1f);
                            point.Scale.X = MathHelper.Lerp(startScale.X, endScale.X, t);
                            point.Scale.Y = MathHelper.Lerp(startScale.Y, endScale.Y, t);
                            point.TexT = t;

                            path.Points.Add(point);
                        }
                    }
                    break;
                case LLObject.PathCurve.Circle:
                    {
                        // Increase the detail as the revolutions and twist increase
                        float twistMag = Math.Abs(prim.PathTwistBegin - prim.PathTwist);

                        int sides = (int)Math.Floor(
                            Math.Floor(MIN_DETAIL_FACES * detail + twistMag * 3.5f * (detail - 0.5f))
                            * prim.PathRevolutions);

                        // FIXME: Sculpty support
                        //if (is_sculpted)
                        //    sides = sculpt_sides(detail);

                        path = GeneratePathPolygon(prim, sides);
                    }
                    break;
                case LLObject.PathCurve.Circle2:
                    {
                        if (prim.PathEnd - prim.PathBegin >= 0.99f && prim.PathScaleX >= 0.99f)
                            path.Open = false;

                        path = GeneratePathPolygon(prim, (int)Math.Floor(MIN_DETAIL_FACES * detail));

                        float t = 0f;
                        float tStep = 1f / path.Points.Count;
                        float toggle = 0.5f;

                        for (int i = 0; i < path.Points.Count; i++)
                        {
                            PathPoint point = path.Points[i];
                            point.Position.X = toggle;
                            path.Points[i] = point;

                            if (toggle == 0.5f)
                                toggle = -0.5f;
                            else
                                toggle = 0.5f;
                            t += tStep;
                        }
                    }
                    break;
                case LLObject.PathCurve.Test:
                    throw new NotImplementedException("PathCurve.Test is not supported");
            }

            if (prim.PathTwist != prim.PathTwistBegin)
                path.Open = true;

            return path;
        }