public void ComputeWorldVertices(Slot slot, float[] worldVertices)
 {
     ComputeWorldVertices(slot, 0, worldVerticesLength, worldVertices, 0);
 }
        /// <summary>Transforms local vertices to world coordinates.</summary>
        /// <param name="start">The index of the first <see cref="Vertices"/> value to transform. Each vertex has 2 values, x and y.</param>
        /// <param name="count">The number of world vertex values to output. Must be less than or equal to <see cref="WorldVerticesLength"/> - start.</param>
        /// <param name="worldVertices">The output world vertices. Must have a length greater than or equal to <paramref name="offset"/> + <paramref name="count"/>.</param>
        /// <param name="offset">The <paramref name="worldVertices"/> index to begin writing values.</param>
        /// <param name="stride">The number of <paramref name="worldVertices"/> entries between the value pairs written.</param>
        public void ComputeWorldVertices(Slot slot, int start, int count, float[] worldVertices, int offset, int stride = 2)
        {
            count = offset + (count >> 1) * stride;
            Skeleton skeleton    = slot.bone.skeleton;
            var      deformArray = slot.attachmentVertices;

            float[] vertices = this.vertices;
            int[]   bones    = this.bones;
            if (bones == null)
            {
                if (deformArray.Count > 0)
                {
                    vertices = deformArray.Items;
                }
                Bone  bone = slot.bone;
                float x = bone.worldX, y = bone.worldY;
                float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
                for (int vv = start, w = offset; w < count; vv += 2, w += stride)
                {
                    float vx = vertices[vv], vy = vertices[vv + 1];
                    worldVertices[w]     = vx * a + vy * b + x;
                    worldVertices[w + 1] = vx * c + vy * d + y;
                }
                return;
            }
            int v = 0, skip = 0;

            for (int i = 0; i < start; i += 2)
            {
                int n = bones[v];
                v    += n + 1;
                skip += n;
            }
            var skeletonBones = skeleton.bones.Items;

            if (deformArray.Count == 0)
            {
                for (int w = offset, b = skip * 3; w < count; w += stride)
                {
                    float wx = 0, wy = 0;
                    int   n = bones[v++];
                    n += v;
                    for (; v < n; v++, b += 3)
                    {
                        Bone  bone = skeletonBones[bones[v]];
                        float vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2];
                        wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
                        wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
                    }
                    worldVertices[w]     = wx;
                    worldVertices[w + 1] = wy;
                }
            }
            else
            {
                float[] deform = deformArray.Items;
                for (int w = offset, b = skip * 3, f = skip << 1; w < count; w += stride)
                {
                    float wx = 0, wy = 0;
                    int   n = bones[v++];
                    n += v;
                    for (; v < n; v++, b += 3, f += 2)
                    {
                        Bone  bone = skeletonBones[bones[v]];
                        float vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2];
                        wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
                        wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
                    }
                    worldVertices[w]     = wx;
                    worldVertices[w + 1] = wy;
                }
            }
        }
示例#3
0
        float[] ComputeWorldPositions(PathAttachment path, int spacesCount, bool tangents, bool percentPosition,
                                      bool percentSpacing)
        {
            Slot  target   = this.target;
            float position = this.position;

            float[] spacesItems = this.spaces.Items, output = this.positions.Resize(spacesCount * 3 + 2).Items, world;
            bool    closed = path.Closed;
            int     verticesLength = path.WorldVerticesLength, curveCount = verticesLength / 6, prevCurve = NONE;

            float pathLength;

            if (!path.ConstantSpeed)
            {
                float[] lengths = path.Lengths;
                curveCount -= closed ? 1 : 2;
                pathLength  = lengths[curveCount];
                if (percentPosition)
                {
                    position *= pathLength;
                }
                if (percentSpacing)
                {
                    for (int i = 0; i < spacesCount; i++)
                    {
                        spacesItems[i] *= pathLength;
                    }
                }
                world = this.world.Resize(8).Items;
                for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3)
                {
                    float space = spacesItems[i];
                    position += space;
                    float p = position;

                    if (closed)
                    {
                        p %= pathLength;
                        if (p < 0)
                        {
                            p += pathLength;
                        }
                        curve = 0;
                    }
                    else if (p < 0)
                    {
                        if (prevCurve != BEFORE)
                        {
                            prevCurve = BEFORE;
                            path.ComputeWorldVertices(target, 2, 4, world, 0);
                        }
                        AddBeforePosition(p, world, 0, output, o);
                        continue;
                    }
                    else if (p > pathLength)
                    {
                        if (prevCurve != AFTER)
                        {
                            prevCurve = AFTER;
                            path.ComputeWorldVertices(target, verticesLength - 6, 4, world, 0);
                        }
                        AddAfterPosition(p - pathLength, world, 0, output, o);
                        continue;
                    }

                    // Determine curve containing position.
                    for (;; curve++)
                    {
                        float length = lengths[curve];
                        if (p > length)
                        {
                            continue;
                        }
                        if (curve == 0)
                        {
                            p /= length;
                        }
                        else
                        {
                            float prev = lengths[curve - 1];
                            p = (p - prev) / (length - prev);
                        }
                        break;
                    }
                    if (curve != prevCurve)
                    {
                        prevCurve = curve;
                        if (closed && curve == curveCount)
                        {
                            path.ComputeWorldVertices(target, verticesLength - 4, 4, world, 0);
                            path.ComputeWorldVertices(target, 0, 4, world, 4);
                        }
                        else
                        {
                            path.ComputeWorldVertices(target, curve * 6 + 2, 8, world, 0);
                        }
                    }
                    AddCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], output, o,
                                     tangents || (i > 0 && space == 0));
                }
                return(output);
            }

            // World vertices.
            if (closed)
            {
                verticesLength += 2;
                world           = this.world.Resize(verticesLength).Items;
                path.ComputeWorldVertices(target, 2, verticesLength - 4, world, 0);
                path.ComputeWorldVertices(target, 0, 2, world, verticesLength - 4);
                world[verticesLength - 2] = world[0];
                world[verticesLength - 1] = world[1];
            }
            else
            {
                curveCount--;
                verticesLength -= 4;
                world           = this.world.Resize(verticesLength).Items;
                path.ComputeWorldVertices(target, 2, verticesLength, world, 0);
            }

            // Curve lengths.
            float[] curves = this.curves.Resize(curveCount).Items;
            pathLength = 0;
            float x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0;
            float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy;

            for (int i = 0, w = 2; i < curveCount; i++, w += 6)
            {
                cx1         = world[w];
                cy1         = world[w + 1];
                cx2         = world[w + 2];
                cy2         = world[w + 3];
                x2          = world[w + 4];
                y2          = world[w + 5];
                tmpx        = (x1 - cx1 * 2 + cx2) * 0.1875f;
                tmpy        = (y1 - cy1 * 2 + cy2) * 0.1875f;
                dddfx       = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375f;
                dddfy       = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375f;
                ddfx        = tmpx * 2 + dddfx;
                ddfy        = tmpy * 2 + dddfy;
                dfx         = (cx1 - x1) * 0.75f + tmpx + dddfx * 0.16666667f;
                dfy         = (cy1 - y1) * 0.75f + tmpy + dddfy * 0.16666667f;
                pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                dfx        += ddfx;
                dfy        += ddfy;
                ddfx       += dddfx;
                ddfy       += dddfy;
                pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                dfx        += ddfx;
                dfy        += ddfy;
                pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                dfx        += ddfx + dddfx;
                dfy        += ddfy + dddfy;
                pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                curves[i]   = pathLength;
                x1          = x2;
                y1          = y2;
            }
            if (percentPosition)
            {
                position *= pathLength;
            }
            if (percentSpacing)
            {
                for (int i = 0; i < spacesCount; i++)
                {
                    spacesItems[i] *= pathLength;
                }
            }

            float[] segments    = this.segments;
            float   curveLength = 0;

            for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3)
            {
                float space = spacesItems[i];
                position += space;
                float p = position;

                if (closed)
                {
                    p %= pathLength;
                    if (p < 0)
                    {
                        p += pathLength;
                    }
                    curve = 0;
                }
                else if (p < 0)
                {
                    AddBeforePosition(p, world, 0, output, o);
                    continue;
                }
                else if (p > pathLength)
                {
                    AddAfterPosition(p - pathLength, world, verticesLength - 4, output, o);
                    continue;
                }

                // Determine curve containing position.
                for (;; curve++)
                {
                    float length = curves[curve];
                    if (p > length)
                    {
                        continue;
                    }
                    if (curve == 0)
                    {
                        p /= length;
                    }
                    else
                    {
                        float prev = curves[curve - 1];
                        p = (p - prev) / (length - prev);
                    }
                    break;
                }

                // Curve segment lengths.
                if (curve != prevCurve)
                {
                    prevCurve = curve;
                    int ii = curve * 6;
                    x1          = world[ii];
                    y1          = world[ii + 1];
                    cx1         = world[ii + 2];
                    cy1         = world[ii + 3];
                    cx2         = world[ii + 4];
                    cy2         = world[ii + 5];
                    x2          = world[ii + 6];
                    y2          = world[ii + 7];
                    tmpx        = (x1 - cx1 * 2 + cx2) * 0.03f;
                    tmpy        = (y1 - cy1 * 2 + cy2) * 0.03f;
                    dddfx       = ((cx1 - cx2) * 3 - x1 + x2) * 0.006f;
                    dddfy       = ((cy1 - cy2) * 3 - y1 + y2) * 0.006f;
                    ddfx        = tmpx * 2 + dddfx;
                    ddfy        = tmpy * 2 + dddfy;
                    dfx         = (cx1 - x1) * 0.3f + tmpx + dddfx * 0.16666667f;
                    dfy         = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f;
                    curveLength = (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                    segments[0] = curveLength;
                    for (ii = 1; ii < 8; ii++)
                    {
                        dfx         += ddfx;
                        dfy         += ddfy;
                        ddfx        += dddfx;
                        ddfy        += dddfy;
                        curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                        segments[ii] = curveLength;
                    }
                    dfx         += ddfx;
                    dfy         += ddfy;
                    curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                    segments[8]  = curveLength;
                    dfx         += ddfx + dddfx;
                    dfy         += ddfy + dddfy;
                    curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                    segments[9]  = curveLength;
                    segment      = 0;
                }

                // Weight by segment length.
                p *= curveLength;
                for (;; segment++)
                {
                    float length = segments[segment];
                    if (p > length)
                    {
                        continue;
                    }
                    if (segment == 0)
                    {
                        p /= length;
                    }
                    else
                    {
                        float prev = segments[segment - 1];
                        p = segment + (p - prev) / (length - prev);
                    }
                    break;
                }
                AddCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, output, o, tangents || (i > 0 && space == 0));
            }
            return(output);
        }