예제 #1
0
        public ConvexHullSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            SampleFramework.IsMouseVisible = false;
            GraphicsScreen.ClearBackground = true;
            GraphicsScreen.BackgroundColor = Color.CornflowerBlue;
            SetCamera(new Vector3F(0, 1, 10), 0, 0);

            // Generate random points.
            var points = new List <Vector3F>();

            for (int i = 0; i < 100; i++)
            {
                points.Add(RandomHelper.Random.NextVector3F(-1, 1));
            }

            // Apply random transformation to points to make this sample more interesting.
            Matrix44F transform = new Matrix44F(
                Matrix33F.CreateRotation(RandomHelper.Random.NextQuaternionF()) * Matrix33F.CreateScale(RandomHelper.Random.NextVector3F(0.1f, 2f)),
                RandomHelper.Random.NextVector3F(-1, 1));

            for (int i = 0; i < points.Count; i++)
            {
                points[i] = transform.TransformPosition(points[i]);
            }

            // Compute convex hull. The result is the mesh of the hull represented as a
            // Doubly-Connected Edge List (DCEL).
            DcelMesh convexHull = GeometryHelper.CreateConvexHull(points);

            // We don't need the DCEL representation. Let's store the hull as a simpler triangle mesh.
            TriangleMesh convexHullMesh = convexHull.ToTriangleMesh();

            // Compute a tight-fitting oriented bounding box.
            Vector3F boundingBoxExtent; // The bounding box dimensions (widths in X, Y and Z).
            Pose     boundingBoxPose;   // The pose (world space position and orientation) of the bounding box.

            GeometryHelper.ComputeBoundingBox(points, out boundingBoxExtent, out boundingBoxPose);
            // (Note: The GeometryHelper also contains methods to compute a bounding sphere.)

            var debugRenderer = GraphicsScreen.DebugRenderer;

            foreach (var point in points)
            {
                debugRenderer.DrawPoint(point, Color.White, true);
            }

            debugRenderer.DrawShape(new TriangleMeshShape(convexHullMesh), Pose.Identity, Vector3F.One, Color.Violet, false, false);
            debugRenderer.DrawBox(boundingBoxExtent.X, boundingBoxExtent.Y, boundingBoxExtent.Z, boundingBoxPose, Color.Red, true, false);
        }
        /// <summary>
        /// Projects a position from world space into screen space.
        /// </summary>
        /// <param name="viewport">The viewport.</param>
        /// <param name="position">The position in view space.</param>
        /// <param name="projection">The projection matrix.</param>
        /// <returns>
        /// The position in screen space: The x- and y-components define the pixel position. The
        /// z-component defines the depth in clip space mapped to the range
        /// [<see cref="Viewport.MinDepth"/>, <see cref="Viewport.MaxDepth"/>] (usually [0, 1]).
        /// </returns>
        public static Vector3F Project(this Viewport viewport, Vector3F position, Matrix44F projection)
        {
            // Transform position to clip space. (TransformPosition() transforms the position
            // to clip space and performs the homogeneous divide.)
            Vector3F positionClip   = projection.TransformPosition(position);
            Vector3F positionScreen = new Vector3F
            {
                X = (1f + positionClip.X) * 0.5f * viewport.Width + viewport.X,
                Y = (1f - positionClip.Y) * 0.5f * viewport.Height + viewport.Y,
                Z = positionClip.Z * (viewport.MaxDepth - viewport.MinDepth) + viewport.MinDepth
            };

            return(positionScreen);
        }
        /// <summary>
        /// Projects a position from world space into viewport.
        /// </summary>
        /// <param name="viewport">The viewport.</param>
        /// <param name="position">The position in view space.</param>
        /// <param name="projection">The projection matrix.</param>
        /// <returns>
        /// The position in the viewport: The x- and y-components define the pixel position
        /// in the range [0, viewport width/height]. The z-component defines the depth in clip space.
        /// </returns>
        internal static Vector3F ProjectToViewport(this Viewport viewport, Vector3F position, Matrix44F projection)
        {
            // Transform position to clip space. (TransformPosition() transforms the position
            // to clip space and performs the homogeneous divide.)
            Vector3F positionClip   = projection.TransformPosition(position);
            Vector3F positionScreen = new Vector3F
            {
                X = (1f + positionClip.X) * 0.5f * viewport.Width,
                Y = (1f - positionClip.Y) * 0.5f * viewport.Height,
                Z = positionClip.Z,
            };

            return(positionScreen);
        }
예제 #4
0
        /// <summary>
        /// Transforms all vertices by the given matrix.
        /// </summary>
        /// <param name="matrix">The transformation matrix.</param>
        public void Transform(Matrix44F matrix)
        {
            if (Vertices == null)
            {
                return;
            }

            int numberOfVertices = Vertices.Count;

            for (int i = 0; i < numberOfVertices; i++)
            {
                Vertices[i] = matrix.TransformPosition(Vertices[i]);
            }
        }
        public static Vector3F Unproject(this Viewport viewport, Vector3F position, Matrix44F projection)
        {
            Matrix44F fromClipSpace = projection.Inverse;
            Vector3F  positionClip  = new Vector3F
            {
                X = (position.X - viewport.X) / viewport.Width * 2f - 1f,
                Y = -((position.Y - viewport.Y) / viewport.Height * 2f - 1f),
                Z = (position.Z - viewport.MinDepth) / (viewport.MaxDepth - viewport.MinDepth),
            };

            // Transform position from clip space to the desired coordinate space.
            // (TransformPosition() undoes the homogeneous divide and transforms the
            // position from clip space to the desired coordinate space.)
            return(fromClipSpace.TransformPosition(positionClip));
        }
예제 #6
0
    public ConvexHullSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      SampleFramework.IsMouseVisible = false;
      GraphicsScreen.ClearBackground = true;
      GraphicsScreen.BackgroundColor = Color.CornflowerBlue;
      SetCamera(new Vector3F(0, 1, 10), 0, 0);

      // Generate random points.
      var points = new List<Vector3F>();
      for (int i = 0; i < 100; i++)
        points.Add(RandomHelper.Random.NextVector3F(-1, 1));

      // Apply random transformation to points to make this sample more interesting.
      Matrix44F transform = new Matrix44F(
        Matrix33F.CreateRotation(RandomHelper.Random.NextQuaternionF()) * Matrix33F.CreateScale(RandomHelper.Random.NextVector3F(0.1f, 2f)),
        RandomHelper.Random.NextVector3F(-1, 1));

      for (int i = 0; i < points.Count; i++)
        points[i] = transform.TransformPosition(points[i]);

      // Compute convex hull. The result is the mesh of the hull represented as a
      // Doubly-Connected Edge List (DCEL).
      DcelMesh convexHull = GeometryHelper.CreateConvexHull(points);

      // We don't need the DCEL representation. Let's store the hull as a simpler triangle mesh.
      TriangleMesh convexHullMesh = convexHull.ToTriangleMesh();

      // Compute a tight-fitting oriented bounding box.
      Vector3F boundingBoxExtent;   // The bounding box dimensions (widths in X, Y and Z).
      Pose boundingBoxPose;         // The pose (world space position and orientation) of the bounding box.
      GeometryHelper.ComputeBoundingBox(points, out boundingBoxExtent, out boundingBoxPose);
      // (Note: The GeometryHelper also contains methods to compute a bounding sphere.)

      var debugRenderer = GraphicsScreen.DebugRenderer;
      foreach (var point in points)
        debugRenderer.DrawPoint(point, Color.White, true);

      debugRenderer.DrawShape(new TriangleMeshShape(convexHullMesh), Pose.Identity, Vector3F.One, Color.Violet, false, false);
      debugRenderer.DrawBox(boundingBoxExtent.X, boundingBoxExtent.Y, boundingBoxExtent.Z, boundingBoxPose, Color.Red, true, false);
    }
 /// <summary>
 /// Projects a position from world space into viewport.
 /// </summary>
 /// <param name="viewport">The viewport.</param>
 /// <param name="position">The position in view space.</param>
 /// <param name="projection">The projection matrix.</param>
 /// <returns>
 /// The position in the viewport: The x- and y-components define the pixel position
 /// in the range [0, viewport width/height]. The z-component defines the depth in clip space.
 /// </returns>
 internal static Vector3F ProjectToViewport(this Viewport viewport, Vector3F position, Matrix44F projection)
 {
     // Transform position to clip space. (TransformPosition() transforms the position
       // to clip space and performs the homogeneous divide.)
       Vector3F positionClip = projection.TransformPosition(position);
       Vector3F positionScreen = new Vector3F
       {
     X = (1f + positionClip.X) * 0.5f * viewport.Width,
     Y = (1f - positionClip.Y) * 0.5f * viewport.Height,
     Z = positionClip.Z,
       };
       return positionScreen;
 }
 /// <summary>
 /// Projects a position from world space into screen space.
 /// </summary>
 /// <param name="viewport">The viewport.</param>
 /// <param name="position">The position in view space.</param>
 /// <param name="projection">The projection matrix.</param>
 /// <returns>
 /// The position in screen space: The x- and y-components define the pixel position. The 
 /// z-component defines the depth in clip space mapped to the range
 /// [<see cref="Viewport.MinDepth"/>, <see cref="Viewport.MaxDepth"/>] (usually [0, 1]).
 /// </returns>
 public static Vector3F Project(this Viewport viewport, Vector3F position, Matrix44F projection)
 {
     // Transform position to clip space. (TransformPosition() transforms the position
       // to clip space and performs the homogeneous divide.)
       Vector3F positionClip = projection.TransformPosition(position);
       Vector3F positionScreen = new Vector3F
       {
     X = (1f + positionClip.X) * 0.5f * viewport.Width + viewport.X,
     Y = (1f - positionClip.Y) * 0.5f * viewport.Height + viewport.Y,
     Z = positionClip.Z * (viewport.MaxDepth - viewport.MinDepth) + viewport.MinDepth
       };
       return positionScreen;
 }
예제 #9
0
        /// <summary>
        /// Draws the batched primitives.
        /// </summary>
        /// <param name="context">The render context.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="context"/> is <see langword="null"/>.
        /// </exception>
        public void Render(RenderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (Effect == null || _primitives.Count == 0)
            {
                return;
            }

            context.Validate(Effect);
            context.ThrowIfCameraMissing();

            var graphicsService  = context.GraphicsService;
            var graphicsDevice   = graphicsService.GraphicsDevice;
            var savedRenderState = new RenderStateSnapshot(graphicsDevice);

            if (AutoRasterizerState)
            {
                graphicsDevice.RasterizerState = DrawWireFrame ? GraphicsHelper.RasterizerStateWireFrame : GraphicsHelper.RasterizerStateCullCounterClockwise;
            }

            // Sort primitives if necessary.
            Matrix44F view = context.CameraNode.View;

            if (SortBackToFront && _usesTransparency)
            {
                // Update depth (distance from camera).
                foreach (var job in _primitives)
                {
                    Vector3F position = job.Pose.Position;
                    job.Depth = view.TransformPosition(position).Z;
                }

                _primitives.Sort(PrimitiveJobDepthComparer.Instance);
            }

            // Reset the texture stages. If a floating point texture is set, we get exceptions
            // when a sampler with bilinear filtering is set.
            graphicsDevice.ResetTextures();

            Effect.LightingEnabled = !DrawWireFrame;
            Effect.TextureEnabled  = false;
            Effect.View            = (Matrix)view;
            Effect.Projection      = context.CameraNode.Camera.Projection;

            foreach (var job in _primitives)
            {
                Effect.Alpha              = job.Color.A / 255.0f;
                Effect.DiffuseColor       = job.Color.ToVector3();
                Effect.VertexColorEnabled = false;

                switch (job.Type)
                {
                case PrimitiveJobType.Box:
                    RenderBox(graphicsService, job);
                    break;

                case PrimitiveJobType.Capsule:
                    RenderCapsule(graphicsService, job);
                    break;

                case PrimitiveJobType.Cone:
                    RenderCone(graphicsService, job);
                    break;

                case PrimitiveJobType.Cylinder:
                    RenderCylinder(graphicsService, job);
                    break;

                case PrimitiveJobType.ViewVolume:
                    RenderViewVolume(job, context);
                    break;

                case PrimitiveJobType.Sphere:
                    RenderSphere(graphicsService, job, context);
                    break;

                case PrimitiveJobType.Shape:
                    RenderShape(graphicsDevice, job);
                    break;

                case PrimitiveJobType.Model:
                    RenderModel(graphicsDevice, job);
                    break;

                case PrimitiveJobType.Submesh:
                    RenderSubmesh(job);
                    break;
                }
            }

            if (DrawWireFrame)
            {
                _lineBatch.Render(context);
                _lineBatch.Clear();
            }

            savedRenderState.Restore();
        }
예제 #10
0
        protected override void OnProcess(RenderContext context)
        {
            context.ThrowIfCameraMissing();

            var graphicsDevice   = GraphicsService.GraphicsDevice;
            var renderTargetPool = GraphicsService.RenderTargetPool;
            var cameraNode       = context.CameraNode;

            var source   = context.SourceTexture;
            var target   = context.RenderTarget;
            var viewport = context.Viewport;

            Projection projection = cameraNode.Camera.Projection;
            Matrix44F  projMatrix = projection;
            float      near       = projection.Near;
            float      far        = projection.Far;

            _frustumInfoParameter.SetValue(new Vector4(
                                               projection.Left / near,
                                               projection.Top / near,
                                               (projection.Right - projection.Left) / near,
                                               (projection.Bottom - projection.Top) / near));

            _numberOfAOSamplesParameter.SetValue(NumberOfSamples);

            // The height of a 1 unit object 1 unit in front of the camera.
            // (Compute 0.5 unit multiply by 2 and divide by 2 to convert from [-1, 1] to [0, 1] range.)
            float projectionScale =
                projMatrix.TransformPosition(new Vector3F(0, 0.5f, -1)).Y
                - projMatrix.TransformPosition(new Vector3F(0, 0, -1)).Y;

            _aoParameters0.SetValue(new Vector4(
                                        projectionScale,
                                        Radius,
                                        Strength / (float)Math.Pow(Radius, 6),
                                        Bias));

            _aoParameters1.SetValue(new Vector4(
                                        viewport.Width,
                                        viewport.Height,
                                        far,
                                        MaxOcclusion));

            _aoParameters2.SetValue(new Vector4(
                                        SampleDistribution,
                                        1.0f / (EdgeSoftness + 0.001f) * far,
                                        BlurScale,
                                        MinBias));

            context.ThrowIfGBuffer0Missing();
            _gBuffer0Parameter.SetValue(context.GBuffer0);

            //var view = cameraNode.View;
            //_viewParameter.SetValue((Matrix)view);
            //_gBuffer1Parameter.SetValue(context.GBuffer1);

            // We use two temporary render targets.
            var format = new RenderTargetFormat(
                context.Viewport.Width,
                context.Viewport.Height,
                false,
                SurfaceFormat.Color,
                DepthFormat.None);

            var tempTarget0 = renderTargetPool.Obtain2D(format);
            var tempTarget1 = renderTargetPool.Obtain2D(format);

            // Create SSAO.
            graphicsDevice.SetRenderTarget(tempTarget0);
            _createAOPass.Apply();

            graphicsDevice.Clear(new Color(1.0f, 1.0f, 1.0f, 1.0f));
            graphicsDevice.DrawFullScreenQuad();

            // Horizontal blur.
            graphicsDevice.SetRenderTarget(tempTarget1);
            _occlusionTextureParameter.SetValue(tempTarget0);
            _blurHorizontalPass.Apply();
            graphicsDevice.DrawFullScreenQuad();

            // Vertical blur
            graphicsDevice.SetRenderTarget(target);
            graphicsDevice.Viewport = viewport;
            _occlusionTextureParameter.SetValue(tempTarget1);
            if (!CombineWithSource)
            {
                _blurVerticalPass.Apply();
            }
            else
            {
                if (_sourceTextureParameter != null)
                {
                    _sourceTextureParameter.SetValue(source);
                }

                if (TextureHelper.IsFloatingPointFormat(source.Format))
                {
                    graphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
                }
                else
                {
                    graphicsDevice.SamplerStates[0] = SamplerState.LinearClamp;
                }

                _blurVerticalAndCombinePass.Apply();
            }

            graphicsDevice.DrawFullScreenQuad();

            // Clean up.
            renderTargetPool.Recycle(tempTarget0);
            renderTargetPool.Recycle(tempTarget1);
            if (_sourceTextureParameter != null)
            {
                _sourceTextureParameter.SetValue((Texture2D)null);
            }
            _occlusionTextureParameter.SetValue((Texture2D)null);
            _gBuffer0Parameter.SetValue((Texture2D)null);
            //_gBuffer1Parameter.SetValue((Texture2D)null);
            context.SourceTexture = source;
            context.RenderTarget  = target;
            context.Viewport      = viewport;
        }
예제 #11
0
    /// <summary>
    /// Transforms all vertices by the given matrix.
    /// </summary>
    /// <param name="matrix">The transformation matrix.</param>
    public void Transform(Matrix44F matrix)
    {
      if (Vertices == null)
        return;

      int numberOfVertices = Vertices.Count;
      for (int i = 0; i < numberOfVertices; i++)
        Vertices[i] = matrix.TransformPosition(Vertices[i]);
    }
예제 #12
0
        private static void CacheVertexBuffer(FigureNode node, GraphicsDevice graphicsDevice)
        {
            var figureRenderData = node.Figure.RenderData;
            var nodeRenderData   = (FigureNodeRenderData)node.RenderData;

            Vector3F[] positions = figureRenderData.Vertices.Array;

            #region ----- Cache vertex/index buffer for fill. -----
            var fillIndices = figureRenderData.FillIndices;
            if (fillIndices != null &&
                fillIndices.Count > 0 &&
                !Numeric.IsZero(node.FillAlpha))
            {
                // This code is similar to the code in Fill().

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

                int numberOfVertices = figureRenderData.Vertices.Count;
                int numberOfIndices  = figureRenderData.FillIndices.Count;

                VertexPositionColor[] vertices = new VertexPositionColor[numberOfVertices];

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

                nodeRenderData.FillVertexBuffer = new VertexBuffer(
                    graphicsDevice,
                    VertexPositionColor.VertexDeclaration,
                    numberOfVertices,
                    BufferUsage.WriteOnly);
                nodeRenderData.FillVertexBuffer.SetData(vertices);

                if (numberOfVertices <= ushort.MaxValue)
                {
                    // Copy all indices from int[] to ushort[].
                    int[]    int32Indices = figureRenderData.FillIndices.Array;
                    ushort[] indices      = new ushort[numberOfIndices];
                    for (int i = 0; i < numberOfIndices; i++)
                    {
                        indices[i] = (ushort)int32Indices[i];
                    }

                    nodeRenderData.FillIndexBuffer = new IndexBuffer(
                        graphicsDevice,
                        IndexElementSize.SixteenBits,
                        numberOfIndices,
                        BufferUsage.WriteOnly);
                    nodeRenderData.FillIndexBuffer.SetData(indices);
                }
                else
                {
                    nodeRenderData.FillIndexBuffer = new IndexBuffer(
                        graphicsDevice,
                        IndexElementSize.ThirtyTwoBits,
                        numberOfIndices,
                        BufferUsage.WriteOnly);
                    // Note: The FillIndices.Array may contain more than numberOfIndices entries! -->
                    // Specify number of indices explicitly!
                    nodeRenderData.FillIndexBuffer.SetData(figureRenderData.FillIndices.Array, 0, numberOfIndices);
                }
            }
            #endregion

            #region ----- Cache vertex/index buffer for stroke. -----

            var strokeIndices = figureRenderData.StrokeIndices;
            if (strokeIndices != null &&
                strokeIndices.Count > 0 &&
                !Numeric.IsZero(node.StrokeThickness) &&
                !Numeric.IsZero(node.StrokeAlpha))
            {
                // This code is similar to the code in Stroke() and in the ctor.

                Matrix44F world = node.PoseWorld * Matrix44F.CreateScale(node.ScaleWorld);

                float       thickness       = node.StrokeThickness;
                Vector3F    color3F         = node.StrokeColor * node.StrokeAlpha;
                HalfVector4 color           = new HalfVector4(color3F.X, color3F.Y, color3F.Z, node.StrokeAlpha);
                Vector4F    dash            = node.StrokeDashPattern * node.StrokeThickness;
                bool        usesDashPattern = (dash.Y + dash.Z) != 0;
                HalfVector4 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;
                Vector3F lastPosition = new Vector3F(float.NaN);
                Vector3F lastWorld    = new Vector3F();

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

                int[] figureIndices        = strokeIndices.Array;
                int   numberOfLineSegments = strokeIndices.Count / 2;
                int   numberOfVertices     = numberOfLineSegments * 4;

                StrokeVertex[] vertices = new StrokeVertex[numberOfVertices];
                for (int i = 0; i < numberOfLineSegments; i++)
                {
                    int      startIndex = figureIndices[i * 2 + 0];
                    int      endIndex   = figureIndices[i * 2 + 1];
                    Vector3F start      = positions[startIndex];
                    Vector3F end        = positions[endIndex];

                    bool notConnectedWithLast = start != lastPosition;
                    lastPosition = end;

                    Vector3F startWorld = notConnectedWithLast ? world.TransformPosition(start) : lastWorld;
                    Vector3F 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)
                    {
                        Debug.Assert(node.DashInWorldSpace, "Cannot cache vertex buffer for figure with screen-space dash patterns.");

                        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;
                    }

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

                    vertices[i * 4 + 0].Start = s;
                    vertices[i * 4 + 0].End   = e;
                    vertices[i * 4 + 0].Data  = data0;
                    vertices[i * 4 + 0].Color = color;
                    vertices[i * 4 + 0].Dash  = dashSum;

                    vertices[i * 4 + 1].Start = s;
                    vertices[i * 4 + 1].End   = e;
                    vertices[i * 4 + 1].Data  = data1;
                    vertices[i * 4 + 1].Color = color;
                    vertices[i * 4 + 1].Dash  = dashSum;

                    vertices[i * 4 + 2].Start = s;
                    vertices[i * 4 + 2].End   = e;
                    vertices[i * 4 + 2].Data  = data2;
                    vertices[i * 4 + 2].Color = color;
                    vertices[i * 4 + 2].Dash  = dashSum;

                    vertices[i * 4 + 3].Start = s;
                    vertices[i * 4 + 3].End   = e;
                    vertices[i * 4 + 3].Data  = data3;
                    vertices[i * 4 + 3].Color = color;
                    vertices[i * 4 + 3].Dash  = dashSum;
                }

                nodeRenderData.StrokeVertexBuffer = new VertexBuffer(
                    graphicsDevice,
                    StrokeVertex.VertexDeclaration,
                    vertices.Length,
                    BufferUsage.WriteOnly);
                nodeRenderData.StrokeVertexBuffer.SetData(vertices);

                // Create stroke indices.
                int numberOfIndices = numberOfLineSegments * 6;
                if (numberOfVertices <= ushort.MaxValue)
                {
                    ushort[] indices = new ushort[numberOfIndices];
                    for (int i = 0; i < numberOfLineSegments; i++)
                    {
                        // Create index buffer for quad (= two triangles, clockwise).
                        //   1--2
                        //   | /|
                        //   |/ |
                        //   0--3
                        indices[i * 6 + 0] = (ushort)(i * 4 + 0);
                        indices[i * 6 + 1] = (ushort)(i * 4 + 1);
                        indices[i * 6 + 2] = (ushort)(i * 4 + 2);
                        indices[i * 6 + 3] = (ushort)(i * 4 + 0);
                        indices[i * 6 + 4] = (ushort)(i * 4 + 2);
                        indices[i * 6 + 5] = (ushort)(i * 4 + 3);
                    }

                    nodeRenderData.StrokeIndexBuffer = new IndexBuffer(
                        graphicsDevice,
                        IndexElementSize.SixteenBits,
                        numberOfIndices,
                        BufferUsage.WriteOnly);
                    nodeRenderData.StrokeIndexBuffer.SetData(indices);
                }
                else
                {
                    int[] indices = new int[numberOfIndices];
                    for (int i = 0; i < numberOfLineSegments; i++)
                    {
                        // Create index buffer for quad (= two triangles, clockwise).
                        //   1--2
                        //   | /|
                        //   |/ |
                        //   0--3
                        indices[i * 6 + 0] = i * 4 + 0;
                        indices[i * 6 + 1] = i * 4 + 1;
                        indices[i * 6 + 2] = i * 4 + 2;
                        indices[i * 6 + 3] = i * 4 + 0;
                        indices[i * 6 + 4] = i * 4 + 2;
                        indices[i * 6 + 5] = i * 4 + 3;
                    }

                    nodeRenderData.StrokeIndexBuffer = new IndexBuffer(
                        graphicsDevice,
                        IndexElementSize.ThirtyTwoBits,
                        numberOfIndices,
                        BufferUsage.WriteOnly);
                    nodeRenderData.StrokeIndexBuffer.SetData(indices);
                }
            }
            #endregion

            nodeRenderData.IsValid = true;
        }
예제 #13
0
        private void Fill(FigureNode node, ArrayList <Vector3F> 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;
#if MONOGAME
                graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, primitiveCount);
#else
                int vertexCount = nodeRenderData.FillVertexBuffer.VertexCount;
                graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertexCount, 0, primitiveCount);
#endif
                return;
            }

            Matrix44F world   = node.PoseWorld * Matrix44F.CreateScale(node.ScaleWorld);
            Vector3F  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.
            Vector3F[] 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]);
            }
        }