Exemple #1
0
        public void Calculate (Vector2 p, Vector2 edgeAB, PenWorkspace ws, PenAlignment alignment, bool start)
        {
            edgeAB.Normalize();

            // [  eAB.X  -eAB.Y ]
            // [  eAB.Y   eAB.X ]

            float tC = edgeAB.X * _width;
            float tS = edgeAB.Y * _width;

            float tX = p.X;
            float tY = p.Y;

            switch (alignment) {
                case PenAlignment.Center:
                    break;

                case PenAlignment.Inset:
                    if (start) {
                        tX = p.X + (-.5f * tS);
                        tY = p.Y - (-.5f * tC);
                    }
                    else {
                        tX = p.X - (-.5f * tS);
                        tY = p.Y + (-.5f * tC);
                    }
                    break;

                case PenAlignment.Outset:
                    if (start) {
                        tX = p.X + (.5f * tS);
                        tY = p.Y - (.5f * tC);
                    }
                    else {
                        tX = p.X - (.5f * tS);
                        tY = p.Y + (.5f * tC);
                    }
                    break;
            }

            for (int i = 0; i < _xyBuffer.Length; i++)
                ws.XYBuffer[i] = new Vector2(_xyBuffer[i].X * tC - _xyBuffer[i].Y * tS + tX, _xyBuffer[i].X * tS + _xyBuffer[i].Y * tC + tY);

            for (int i = 0; i < _uvBuffer.Length; i++)
                ws.UVBuffer[i] = _uvBuffer[i];

            for (int i = 0; i < _indexBuffer.Length; i++)
                ws.IndexBuffer[i] = _indexBuffer[i];

            for (int i = 0; i < _outlineBuffer.Length; i++)
                ws.OutlineIndexBuffer[i] = _outlineBuffer[i];

            ws.XYBuffer.Index = _xyBuffer.Length;
            ws.UVBuffer.Index = _uvBuffer.Length;
            ws.IndexBuffer.Index = _indexBuffer.Length;
            ws.OutlineIndexBuffer.Index = _outlineBuffer.Length;
        }
Exemple #2
0
        internal void ComputeEndPoint (Vector2 a, Vector2 b, PenWorkspace ws)
        {
            EndCapInfo.Calculate(b, a - b, ws, Alignment, false);

            for (int i = 0; i < ws.UVBuffer.Index; i++)
                ws.UVBuffer[i] = new Vector2(1 - ws.UVBuffer[i].X, ws.PathLength);
        }
Exemple #3
0
 internal void ComputeStartPoint (Vector2 a, Vector2 b, PenWorkspace ws)
 {
     StartCapInfo.Calculate(a, b - a, ws, Alignment, true);
 }
Exemple #4
0
        //internal InsetOutsetCount ComputeBevel (Vector2 a, Vector2 b, Vector2 c, PenWorkspace ws)
        internal InsetOutsetCount ComputeBevel (ref JoinSample js, PenWorkspace ws)
        {
            Vector2 a = js.PointA;
            Vector2 b = js.PointB;
            Vector2 c = js.PointC;

            Vector2 edgeBA = new Vector2(a.X - b.X, a.Y - b.Y);
            Vector2 edgeBC = new Vector2(c.X - b.X, c.Y - b.Y);
            double dot = Vector2.Dot(edgeBA, edgeBC);
            if (dot < 0) {
                double den = edgeBA.LengthSquared() * edgeBC.LengthSquared();
                double cos2 = (dot * dot) / den;

                if (cos2 > _joinLimitCos2)
                    return ComputeMiter(ref js, ws);
            }

            Vector2 edgeAB = new Vector2(b.X - a.X, b.Y - a.Y);
            edgeAB.Normalize();
            Vector2 edgeABt = new Vector2(-edgeAB.Y, edgeAB.X);

            edgeBC.Normalize();
            Vector2 edgeBCt = new Vector2(-edgeBC.Y, edgeBC.X);

            Vector2 pointA = a;
            Vector2 pointC = c;

            short vertexCount = 0;

            if (Cross2D(edgeAB, edgeBC) > 0) {
                switch (Alignment) {
                    case PenAlignment.Center:
                        float w2 = Width / 2;
                        pointA = new Vector2(a.X - w2 * edgeABt.X, a.Y - w2 * edgeABt.Y);
                        pointC = new Vector2(c.X - w2 * edgeBCt.X, c.Y - w2 * edgeBCt.Y);

                        ws.XYInsetBuffer[0] = new Vector2(b.X + w2 * edgeABt.X, b.Y + w2 * edgeABt.Y);
                        ws.XYInsetBuffer[1] = new Vector2(b.X + w2 * edgeBCt.X, b.Y + w2 * edgeBCt.Y);

                        vertexCount = 2;
                        break;

                    case PenAlignment.Inset:
                        ws.XYInsetBuffer[0] = new Vector2(b.X + Width * edgeABt.X, b.Y + Width * edgeABt.Y);
                        ws.XYInsetBuffer[1] = new Vector2(b.X + Width * edgeBCt.X, b.Y + Width * edgeBCt.Y);

                        vertexCount = 2;
                        break;

                    case PenAlignment.Outset:
                        pointA = new Vector2(a.X - Width * edgeABt.X, a.Y - Width * edgeABt.Y);
                        pointC = new Vector2(c.X - Width * edgeBCt.X, c.Y - Width * edgeBCt.Y);

                        ws.XYInsetBuffer[0] = b;

                        vertexCount = 1;
                        break;
                }

                Vector2 point5;

                float tdiv = Vector2.Dot(edgeBCt, edgeAB);
                if (Math.Abs(tdiv) < 0.0005f) {
                    point5 = new Vector2((pointA.X + pointC.X) / 2, (pointA.Y + pointC.Y) / 2);
                }
                else {
                    float offset35 = Vector2.Dot(edgeBCt, pointC);
                    float t5 = (offset35 - Vector2.Dot(edgeBCt, pointA)) / tdiv;

                    point5 = new Vector2(pointA.X + t5 * edgeAB.X, pointA.Y + t5 * edgeAB.Y);
                }

                ws.XYOutsetBuffer[0] = point5;

                ws.UVOutsetBuffer[0] = new Vector2(1, js.LengthB);
                for (int i = 0; i < vertexCount; i++)
                    ws.UVInsetBuffer[i] = new Vector2(0, js.LengthB);

                return new InsetOutsetCount(vertexCount, 1, false);
            }
            else {
                switch (Alignment) {
                    case PenAlignment.Center:
                        float w2 = Width / 2;
                        pointA = new Vector2(a.X + w2 * edgeABt.X, a.Y + w2 * edgeABt.Y);
                        pointC = new Vector2(c.X + w2 * edgeBCt.X, c.Y + w2 * edgeBCt.Y);

                        ws.XYOutsetBuffer[0] = new Vector2(b.X - w2 * edgeABt.X, b.Y - w2 * edgeABt.Y);
                        ws.XYOutsetBuffer[1] = new Vector2(b.X - w2 * edgeBCt.X, b.Y - w2 * edgeBCt.Y);

                        vertexCount = 2;
                        break;

                    case PenAlignment.Inset:
                        pointA = new Vector2(a.X + Width * edgeABt.X, a.Y + Width * edgeABt.Y);
                        pointC = new Vector2(c.X + Width * edgeBCt.X, c.Y + Width * edgeBCt.Y);

                        ws.XYOutsetBuffer[0] = b;

                        vertexCount = 1;
                        break;

                    case PenAlignment.Outset:
                        ws.XYOutsetBuffer[0] = new Vector2(b.X - Width * edgeABt.X, b.Y - Width * edgeABt.Y);
                        ws.XYOutsetBuffer[1] = new Vector2(b.X - Width * edgeBCt.X, b.Y - Width * edgeBCt.Y);

                        vertexCount = 2;
                        break;
                }

                Vector2 point0;

                float tdiv = Vector2.Dot(edgeBCt, edgeAB);
                if (Math.Abs(tdiv) < 0.0005f) {
                    point0 = new Vector2((pointA.X + pointC.X) / 2, (pointA.Y + pointC.Y) / 2);
                }
                else {
                    float offset01 = Vector2.Dot(edgeBCt, pointC);
                    float t0 = (offset01 - Vector2.Dot(edgeBCt, pointA)) / tdiv;

                    point0 = new Vector2(pointA.X + t0 * edgeAB.X, pointA.Y + t0 * edgeAB.Y);
                }

                ws.XYInsetBuffer[0] = point0;

                ws.UVInsetBuffer[0] = new Vector2(0, js.LengthB);
                for (int i = 0; i < vertexCount; i++)
                    ws.UVOutsetBuffer[i] = new Vector2(1, js.LengthB);

                return new InsetOutsetCount(1, vertexCount, true);
            }
        }
Exemple #5
0
        //internal InsetOutsetCount ComputeMiter (Vector2 a, Vector2 b, Vector2 c, PenWorkspace ws)
        internal InsetOutsetCount ComputeMiter (ref JoinSample js, PenWorkspace ws)
        {
            Vector2 a = js.PointA;
            Vector2 b = js.PointB;
            Vector2 c = js.PointC;

            Vector2 edgeAB = new Vector2(b.X - a.X, b.Y - a.Y);
            edgeAB.Normalize();
            Vector2 edgeABt = new Vector2(-edgeAB.Y, edgeAB.X);

            Vector2 edgeBC = new Vector2(c.X - b.X, c.Y - b.Y);
            edgeBC.Normalize();
            Vector2 edgeBCt = new Vector2(-edgeBC.Y, edgeBC.X);

            Vector2 point1, point2, point3, point4;

            switch (Alignment) {
                case PenAlignment.Center:
                    float w2 = Width / 2;

                    point2 = new Vector2(a.X + w2 * edgeABt.X, a.Y + w2 * edgeABt.Y);
                    point4 = new Vector2(a.X - w2 * edgeABt.X, a.Y - w2 * edgeABt.Y);

                    point1 = new Vector2(c.X + w2 * edgeBCt.X, c.Y + w2 * edgeBCt.Y);
                    point3 = new Vector2(c.X - w2 * edgeBCt.X, c.Y - w2 * edgeBCt.Y);
                    break;

                case PenAlignment.Inset:
                    point2 = new Vector2(a.X + Width * edgeABt.X, a.Y + Width * edgeABt.Y);
                    point4 = a;

                    point1 = new Vector2(c.X + Width * edgeBCt.X, c.Y + Width * edgeBCt.Y);
                    point3 = c;
                    break;

                case PenAlignment.Outset:
                    point2 = a;
                    point4 = new Vector2(a.X - Width * edgeABt.X, a.Y - Width * edgeABt.Y);

                    point1 = c;
                    point3 = new Vector2(c.X - Width * edgeBCt.X, c.Y - Width * edgeBCt.Y);
                    break;

                default:
                    point2 = Vector2.Zero;
                    point4 = Vector2.Zero;

                    point1 = Vector2.Zero;
                    point3 = Vector2.Zero;
                    break;
            }

            Vector2 point0, point5;

            float tdiv = Vector2.Dot(edgeBCt, edgeAB);

            if (Math.Abs(tdiv) < .0005f) {
                point0 = new Vector2((point2.X + point1.X) / 2, (point2.Y + point1.Y) / 2);
                point5 = new Vector2((point4.X + point3.X) / 2, (point4.Y + point3.Y) / 2);
            }
            else {
                float offset01 = Vector2.Dot(edgeBCt, point1);
                float t0 = (offset01 - Vector2.Dot(edgeBCt, point2)) / tdiv;

                float offset35 = Vector2.Dot(edgeBCt, point3);
                float t5 = (offset35 - Vector2.Dot(edgeBCt, point4)) / tdiv;

                point0 = new Vector2(point2.X + t0 * edgeAB.X, point2.Y + t0 * edgeAB.Y);
                point5 = new Vector2(point4.X + t5 * edgeAB.X, point4.Y + t5 * edgeAB.Y);
            }

            double miterLimit = MiterLimit * Width;
            if ((point0 - point5).LengthSquared() > miterLimit * miterLimit)
                return ComputeBevel(ref js, ws);

            ws.XYInsetBuffer[0] = point0;
            ws.XYOutsetBuffer[0] = point5;

            ws.UVInsetBuffer[0] = new Vector2(0, js.LengthB);
            ws.UVOutsetBuffer[0] = new Vector2(1, js.LengthB);

            return new InsetOutsetCount(1, 1);
        }
        private void AddPath (CCVector2[] points, int offset, int count, Pen pen, PenWorkspace ws)
        {
            RequestBufferSpace(count * 2, (count - 1) * 6);
            _ws.ResetWorkspace(pen);

            AddInfo(PrimitiveType.TriangleList, count * 2, (count - 1) * 6, pen.Brush);

            int baseVertexIndex = _vertexBufferIndex;

            AddStartPoint(points[offset + 0], points[offset + 1], pen, _ws);

            JoinSample js = new JoinSample(CCVector2.Zero, points[offset + 0], points[offset + 1]);

            for (int i = 0; i < count - 2; i++) {
                js.Advance(points[offset + i + 2]);
                AddMiteredJoint(ref js, pen, ws);
            }

            AddEndPoint(points[offset + count - 2], points[offset + count - 1], pen, _ws);

            for (int i = 0; i < count - 1; i++)
                AddSegment(baseVertexIndex + i * 2, baseVertexIndex + (i + 1) * 2);
        }
        /// <summary>
        /// Enables a group of figures to be drawn using the same settings.
        /// </summary>
        /// <param name="device"></param>
        //public DrawBatch (GraphicsDevice device)
        //{
        public DrawBatch () : base()
        {
            //if (device == null)
            //    throw new ArgumentNullException("device");

            //_device = device;
            //_device.DeviceReset += GraphicsDeviceReset;

            _infoBuffer = new DrawingInfo[2048];
            _indexBuffer = new short[32768];
            //_vertexBuffer = new VertexPositionColorTexture[8192];
            _computeBuffer = new CCVector2[64];
            _colorBuffer = new Color[64];
            _geometryBuffer = new CCVector2[256];
            _pathBuilder = new PathBuilder();

            //_standardEffect = new BasicEffect(device);
            //_standardEffect.TextureEnabled = true;
            //_standardEffect.VertexColorEnabled = true;

            //_defaultTexture = new Texture2D(device, 1, 1);
            //_defaultTexture.SetData<Color>(new Color[] { Microsoft.Xna.Framework.Color.White });

            _ws = new PenWorkspace();
        }
        /// <summary>
        /// Immediatley renders a <see cref="DrawCache"/> object.
        /// </summary>
        /// <param name="cache">A <see cref="DrawCache"/> object.</param>
        /// <remarks>Any previous unflushed geometry will be rendered first.</remarks>
        //public void DrawCache (DrawCache cache)
        //{
        //    if (_sortMode != DrawSortMode.Immediate)
        //        SetRenderState();

        //    FlushBuffer();

        //    cache.Render(_device, _defaultTexture);
        //}

        //private void SetRenderState ()
        //{
        //    _device.BlendState = (_blendState != null)
        //        ? _blendState : BlendState.AlphaBlend;

        //    _device.DepthStencilState = (_depthStencilState != null)
        //        ? _depthStencilState : DepthStencilState.None;

        //    _device.RasterizerState = (_rasterizerState != null)
        //        ? _rasterizerState : RasterizerState.CullCounterClockwise;

        //    _device.SamplerStates[0] = (_samplerState != null)
        //        ? _samplerState : SamplerState.PointWrap;

        //    _standardEffect.Projection = Matrix.CreateOrthographicOffCenter(0, _device.Viewport.Width, _device.Viewport.Height, 0, -1, 1);
        //    _standardEffect.World = _transform;
        //    _standardEffect.CurrentTechnique.Passes[0].Apply();

        //    if (_effect != null)
        //        _effect.CurrentTechnique.Passes[0].Apply();
        //}

        private void AddMiteredJoint (ref JoinSample js, Pen pen, PenWorkspace ws)
        {
            InsetOutsetCount vioCount = pen.ComputeMiter(ref js, ws);

            AddVertex(ws.XYInsetBuffer[0], pen.ColorAt(ws.UVInsetBuffer[0], ws.PathLengthScale), pen);
            AddVertex(ws.XYOutsetBuffer[0], pen.ColorAt(ws.UVOutsetBuffer[0], ws.PathLengthScale), pen);
        }
        private void AddEndPoint (CCVector2 a, CCVector2 b, Pen pen, PenWorkspace ws)
        {
            pen.ComputeEndPoint(a, b, ws);

            AddVertex(ws.XYBuffer[0], pen.ColorAt(ws.UVBuffer[0], ws.PathLengthScale), pen);
            AddVertex(ws.XYBuffer[1], pen.ColorAt(ws.UVBuffer[1], ws.PathLengthScale), pen);
        }
Exemple #10
0
        private int AddJoint (int pointIndex, InsetOutsetCount vioCount, PenWorkspace ws)
        {
            int vIndex = _vertexBufferIndex;

            _vertexBufferIndex += vioCount.InsetCount + vioCount.OutsetCount;

            if (!vioCount.CCW) {
                _jointCCW[pointIndex] = false;
                _positionData[vIndex + 0] = ws.XYOutsetBuffer[0];
                for (int i = 0; i < vioCount.InsetCount; i++)
                    _positionData[vIndex + 1 + i] = ws.XYInsetBuffer[i];

                for (int i = 0; i < vioCount.InsetCount - 1; i++) {
                    _indexData[_indexBufferIndex++] = (short)(vIndex);
                    _indexData[_indexBufferIndex++] = (short)(vIndex + i + 2);
                    _indexData[_indexBufferIndex++] = (short)(vIndex + i + 1);
                }
            }
            else {
                _jointCCW[pointIndex] = true;
                _positionData[vIndex + 0] = ws.XYInsetBuffer[0];
                for (int i = 0; i < vioCount.OutsetCount; i++)
                    _positionData[vIndex + 1 + i] = ws.XYOutsetBuffer[i];

                for (int i = 0; i < vioCount.OutsetCount - 1; i++) {
                    _indexData[_indexBufferIndex++] = (short)(vIndex);
                    _indexData[_indexBufferIndex++] = (short)(vIndex + i + 1);
                    _indexData[_indexBufferIndex++] = (short)(vIndex + i + 2);
                }
            }

            if (_colorData != null) {
                if (!vioCount.CCW) {
                    _colorData[vIndex] = _pen.ColorAt(ws.UVOutsetBuffer[0], ws.PathLengthScale);
                    for (int i = 0; i < vioCount.InsetCount; i++)
                        _colorData[vIndex + 1 + i] = _pen.ColorAt(ws.UVInsetBuffer[i], ws.PathLengthScale);
                }
                else {
                    _colorData[vIndex] = _pen.ColorAt(ws.UVInsetBuffer[0], ws.PathLengthScale);
                    for (int i = 0; i < vioCount.OutsetCount; i++)
                        _colorData[vIndex + 1 + i] = _pen.ColorAt(ws.UVOutsetBuffer[i], ws.PathLengthScale);
                }
            }

            if (_textureData != null) {
                int texWidth = _pen.Brush.Texture.Width;
                int texHeight = _pen.Brush.Texture.Height;

                for (int i = vIndex; i < _vertexBufferIndex; i++) {
                    Vector2 pos = _positionData[i];
                    _textureData[i] = new Vector2(pos.X / texWidth, pos.Y / texHeight);
                }
            }

            return _vertexBufferIndex - vIndex;
        }
Exemple #11
0
        private int AddJoint (int pointIndex, ref JoinSample joinSample, PenWorkspace ws, Buffer<Vector2> insetBuffer, Buffer<Vector2> outsetBuffer)
        {
            InsetOutsetCount vioCount = new InsetOutsetCount();

            switch (_pen.LineJoin) {
                case LineJoin.Miter:
                    vioCount = _pen.ComputeMiter(ref joinSample, ws);
                    break;
                case LineJoin.Bevel:
                    vioCount = _pen.ComputeBevel(ref joinSample, ws);
                    break;
            }

            if (insetBuffer != null) {
                for (int i = 0; i < vioCount.InsetCount; i++)
                    insetBuffer.SetNext(ws.XYInsetBuffer[i]);
            }
            if (outsetBuffer != null) {
                for (int i = 0; i < vioCount.OutsetCount; i++)
                    outsetBuffer.SetNext(ws.XYOutsetBuffer[i]);
            }

            return (_strokeType != StrokeType.Outline) ? AddJoint(pointIndex, vioCount, ws) : 0;
        }
Exemple #12
0
        private int AddStartOrEndPoint (int pointIndex, PenWorkspace ws, Buffer<Vector2> positionBuffer, bool ccw)
        {
            int xyCount = ws.XYBuffer.Index;

            if (positionBuffer != null) {
                for (int i = 0; i < ws.OutlineIndexBuffer.Index; i++)
                    positionBuffer.SetNext(ws.XYBuffer[ws.OutlineIndexBuffer[i]]);
            }

            if (_strokeType == StrokeType.Outline)
                return 0;

            int baseIndex = _vertexBufferIndex;

            _vertexBufferIndex += xyCount;

            for (int i = 0; i < xyCount; i++)
                _positionData[baseIndex + i] = ws.XYBuffer[i];

            for (int i = 0; i < ws.IndexBuffer.Index; i++)
                _indexData[_indexBufferIndex++] = (short)(baseIndex + ws.IndexBuffer[i]);

            if (_colorData != null) {
                for (int i = 0; i < xyCount; i++)
                    _colorData[baseIndex + i] = _pen.ColorAt(ws.UVBuffer[i], ws.PathLengthScale);
            }

            if (_textureData != null) {
                int texWidth = _pen.Brush.Texture.Width;
                int texHeight = _pen.Brush.Texture.Height;

                for (int i = baseIndex; i < _vertexBufferIndex; i++) {
                    Vector2 pos = _positionData[i];
                    _textureData[i] = new Vector2(pos.X / texWidth, pos.Y / texHeight);
                }
            }

            _jointCCW[pointIndex] = ccw;

            return xyCount;
        }
Exemple #13
0
        private int AddEndPoint (int pointIndex, Vector2 a, Vector2 b, PenWorkspace ws, Buffer<Vector2> positionBuffer)
        {
            _pen.ComputeEndPoint(a, b, ws);

            int xyCount = AddStartOrEndPoint(pointIndex, ws, positionBuffer, true);

            return xyCount;
        }
Exemple #14
0
        private int AddStartPoint (int pointIndex, Vector2 a, Vector2 b, PenWorkspace ws, Buffer<Vector2> positionBuffer)
        {
            _pen.ComputeStartPoint(a, b, ws);

            int xyCount = AddStartOrEndPoint(pointIndex, ws, positionBuffer, false);

            if (positionBuffer != null)
                Array.Reverse(positionBuffer.Data, positionBuffer.Index - ws.OutlineIndexBuffer.Index, ws.OutlineIndexBuffer.Index);

            return xyCount;
        }