Esempio n. 1
0
        /// <inheritdoc/>
        public void DrawBillboard(ref BillboardArgs billboard, PackedTexture texture)
        {
            int index, dummy;

            _renderBatch.Submit(PrimitiveType.TriangleList, 4, 6, out index, out dummy);

            OnDrawBillboard(ref billboard, texture, _renderBatch.Vertices, index);
        }
Esempio n. 2
0
    private void Stroke(FigureNode node, ArrayList<Vector3> strokeVertices, ArrayList<int> strokeIndices)
    {
      if (_mode != RenderMode.Stroke)
      {
        Flush();
        _strokeEffect.CurrentTechnique.Passes[0].Apply();
        _mode = RenderMode.Stroke;
      }

      // Use cached vertex buffer if available.
      var nodeRenderData = node.RenderData as FigureNodeRenderData;
      if (nodeRenderData != null && nodeRenderData.IsValid)
      {
        Flush();
        var graphicsDevice = _graphicsService.GraphicsDevice;
        graphicsDevice.SetVertexBuffer(nodeRenderData.StrokeVertexBuffer);
        graphicsDevice.Indices = nodeRenderData.StrokeIndexBuffer;
        int primitiveCount = nodeRenderData.StrokeIndexBuffer.IndexCount / 3;

        graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, primitiveCount);
#else
        int vertexCount = nodeRenderData.StrokeVertexBuffer.VertexCount;
        graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertexCount, 0, primitiveCount);

        return;
      }

      var batchVertices = _strokeBatch.Vertices;

      var world = node.PoseWorld * Matrix.CreateScale(node.ScaleWorld);
      var worldView = _view * world;

      var thickness = node.StrokeThickness;
      var color3F = node.StrokeColor * node.StrokeAlpha;
      var color = new HalfVector4(color3F.X, color3F.Y, color3F.Z, node.StrokeAlpha);
      var dash = node.StrokeDashPattern * node.StrokeThickness;
      bool usesDashPattern = (dash.Y + dash.Z) != 0;
      var dashSum = new HalfVector4(
        dash.X,
        dash.X + dash.Y,
        dash.X + dash.Y + dash.Z,
        dash.X + dash.Y + dash.Z + dash.W);

      // Convert to vertices.
      float lastDistance = 0;
      Vector3 lastPosition = new Vector3(float.NaN);
      Vector3 lastWorld = new Vector3();
      Vector3 lastView = new Vector3();
      Vector3 lastProjected = new Vector3();

      var data0 = new HalfVector4(0, 1, thickness, 0);
      var data1 = new HalfVector4(0, 0, thickness, 0);
      var data2 = new HalfVector4(1, 0, thickness, 0);
      var data3 = new HalfVector4(1, 1, thickness, 0);

      Vector3[] figurePoints = strokeVertices.Array;
      int[] figureIndices = strokeIndices.Array;
      int numberOfLineSegments = strokeIndices.Count / 2;

      for (int i = 0; i < numberOfLineSegments; i++)
      {
        var startIndex = figureIndices[i * 2 + 0];
        var endIndex = figureIndices[i * 2 + 1];
        var start = figurePoints[startIndex];
        var end = figurePoints[endIndex];

        var notConnectedWithLast = start != lastPosition;
        lastPosition = end;

        Vector3 startWorld = notConnectedWithLast ? world.TransformPosition(start) : lastWorld;
        Vector3 endWorld = world.TransformPosition(end);
        lastWorld = endWorld;

        // Compute start/end distances of lines from beginning of line strip
        // for dash patterns.
        float startDistance = 0;
        float endDistance = 1;
        if (usesDashPattern)
        {
          if (!node.DashInWorldSpace)
          {
            Vector3 startView = notConnectedWithLast ? worldView.TransformPosition(start) : lastView;
            var endView = worldView.TransformPosition(end);
            lastView = endView;

            // Clip to near plane - otherwise lines which end near the camera origin
            // (where planar z == 0) will disappear. (Projection singularity!)
            float deltaZ = Math.Abs(startView.Z - endView.Z);
            float pStart = MathHelper.Clamp((startView.Z - (-_cameraNear)) / deltaZ, 0, 1);
            startView = InterpolationHelper.Lerp(startView, endView, pStart);
            float pEnd = MathHelper.Clamp((endView.Z - (-_cameraNear)) / deltaZ, 0, 1);
            endView = InterpolationHelper.Lerp(endView, startView, pEnd);

            Vector3 startProjected;
            if (notConnectedWithLast)
            {
              lastDistance = 0;
              startProjected = _viewport.ProjectToViewport(startView, _projection);
            }
            else
            {
              startProjected = lastProjected;
            }
            var endProjected = _viewport.ProjectToViewport(endView, _projection);
            lastProjected = endProjected;

            startDistance = lastDistance;
            endDistance = startDistance + (endProjected - startProjected).Length;
            lastDistance = endDistance;
          }
          else
          {
            if (notConnectedWithLast)
              lastDistance = 0;

            startDistance = lastDistance;
            endDistance = startDistance + (endWorld - startWorld).Length;
            lastDistance = endDistance;

            // The shader needs to know that DashInWorldSpace is true. To avoid
            // effect parameter changes, we store the value in the sign of the distance!
            startDistance = -startDistance;
            endDistance = -endDistance;
          }
        }

        var s = new Vector4(startWorld.X, startWorld.Y, startWorld.Z, startDistance);
        var e = new Vector4(endWorld.X, endWorld.Y, endWorld.Z, endDistance);

        int index, dummy;
        _strokeBatch.Submit(PrimitiveType.TriangleList, 4, 6, out index, out dummy);

        batchVertices[index + 0].Start = s;
        batchVertices[index + 0].End = e;
        batchVertices[index + 0].Data = data0;
        batchVertices[index + 0].Color = color;
        batchVertices[index + 0].Dash = dashSum;

        batchVertices[index + 1].Start = s;
        batchVertices[index + 1].End = e;
        batchVertices[index + 1].Data = data1;
        batchVertices[index + 1].Color = color;
        batchVertices[index + 1].Dash = dashSum;

        batchVertices[index + 2].Start = s;
        batchVertices[index + 2].End = e;
        batchVertices[index + 2].Data = data2;
        batchVertices[index + 2].Color = color;
        batchVertices[index + 2].Dash = dashSum;

        batchVertices[index + 3].Start = s;
        batchVertices[index + 3].End = e;
        batchVertices[index + 3].Data = data3;
        batchVertices[index + 3].Color = color;
        batchVertices[index + 3].Dash = dashSum;
      }
    }
Esempio n. 3
0
    private void Fill(FigureNode node, ArrayList<Vector3> vertices, ArrayList<int> indices)
    {
      if (_mode != RenderMode.Fill)
      {
        Flush();
        _fillEffect.CurrentTechnique.Passes[0].Apply();
        _mode = RenderMode.Fill;
      }

      // Use cached vertex buffer if available.
      var nodeRenderData = node.RenderData as FigureNodeRenderData;
      if (nodeRenderData != null && nodeRenderData.IsValid)
      {
        Flush();
        var graphicsDevice = _graphicsService.GraphicsDevice;
        graphicsDevice.SetVertexBuffer(nodeRenderData.FillVertexBuffer);
        graphicsDevice.Indices = nodeRenderData.FillIndexBuffer;
        int primitiveCount = nodeRenderData.FillIndexBuffer.IndexCount / 3;

        graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, primitiveCount);
#else
        int vertexCount = nodeRenderData.FillVertexBuffer.VertexCount;
        graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertexCount, 0, primitiveCount);

        return;
      }

      Matrix world = node.PoseWorld * Matrix.CreateScale(node.ScaleWorld);
      Vector3 color3F = node.FillColor * node.FillAlpha;
      Color color = new Color(color3F.X, color3F.Y, color3F.Z, node.FillAlpha);

      var numberOfVertices = vertices.Count;
      var numberOfIndices = indices.Count;

      VertexPositionColor[] batchVertices = _fillBatch.Vertices;
      ushort[] batchIndices = _fillBatch.Indices;

      if (numberOfVertices > batchVertices.Length || numberOfIndices > batchIndices.Length)
      {
        string message = string.Format(
          CultureInfo.InvariantCulture,
          "The BufferSize of this FigureRenderer is not large enough to render the FigureNode (Name = \"{0}\").",
          node.Name);
        throw new GraphicsException(message);
      }

      int vertexBufferStartIndex, indexBufferStartIndex;
      _fillBatch.Submit(PrimitiveType.TriangleList, numberOfVertices, numberOfIndices,
        out vertexBufferStartIndex, out indexBufferStartIndex);

      // Copy all vertices.
      Vector3[] vertexArray = vertices.Array;
      for (int i = 0; i < numberOfVertices; i++)
      {
        batchVertices[vertexBufferStartIndex + i].Position = (Vector3)(world.TransformPosition(vertexArray[i]));
        batchVertices[vertexBufferStartIndex + i].Color = color;
      }

      // Copy all indices.
      int[] indexArray = indices.Array;
      for (int i = 0; i < numberOfIndices; i++)
      {
        batchIndices[indexBufferStartIndex + i] = (ushort)(vertexBufferStartIndex + indexArray[i]);
      }
    }