Click here to Skip to main content
15,897,273 members
Articles / Desktop Programming / WPF

D3dHost - MDX and WPF interoperability

Rate me:
Please Sign up or sign in to vote.
5.00/5 (7 votes)
13 Nov 2012CPOL5 min read 34.2K   2.6K   20  
This article shows how we can render an interoperable MDX (Managed DirectX) scene, inside a WPF window.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Media3D;

namespace MdxWpfInteroperability.Example
{
    public static class WpfSceneRenderer
    {
        public static void WpfRenderScene(SceneData scene, 
            Viewport3D viewport3d)
        {
            if (scene == null || viewport3d == null)
            {
                return;
            }

            viewport3d.Children.Clear();

            // Init camera matrices
            viewport3d.Camera = new PerspectiveCamera
            {
                Position = scene.CameraPosition,
                UpDirection = new Vector3D(0, 1, 0),
                FarPlaneDistance = scene.FarPlaneDistance
            };

            // Add directional light
            Vector3D lightDirection = 
                new Vector3D(-1, -1, -1);
            lightDirection.Normalize();
            ModelVisual3D dirlight = new ModelVisual3D
            {
                Content = new DirectionalLight(
                    Colors.White, lightDirection)
            };
            viewport3d.Children.Add(dirlight);

            foreach (ConeData cone in scene.Cones)
            {
                WpfRenderCone(cone, viewport3d);
            }
        }

        private static void WpfRenderCone(ConeData cone,
            Viewport3D viewport3d)
        {
            // Create the cone's material
            DiffuseMaterial coneMaterial =
                new DiffuseMaterial(
                    new SolidColorBrush(
                        cone.MaterialColor));

            // Create the cone's geometry

            int numOfPoints = (int)cone.BaseRadius;
            if (numOfPoints < 10)
            {
                numOfPoints = 10;
            }

            double partAngle = Math.PI * 2 / numOfPoints;

            // Create the vertices' collections.
            MeshGeometry3D coneMesh = new MeshGeometry3D();
            coneMesh.Positions = new Point3DCollection();
            coneMesh.Normals = new Vector3DCollection();
            coneMesh.TriangleIndices = new Int32Collection();

            // Set the top vertex.
            coneMesh.Positions.Add(new Point3D(
                0, cone.Height / 2, 0));
            coneMesh.Normals.Add(new Vector3D(0, 1, 0));

            // Set the base center vertex.
            coneMesh.Positions.Add(new Point3D(
                0, cone.Height / -2, 0));
            coneMesh.Normals.Add(new Vector3D(0, -1, 0));

            double bodyNormalY =
                Math.Sin(Math.PI -
                    Math.Atan(cone.Height / 
                        cone.BaseRadius) * 2) *
                Math.Sqrt(cone.Height * cone.Height +
                    cone.BaseRadius * cone.BaseRadius);

            for (int vertexInx = 0; vertexInx <= numOfPoints; vertexInx++)
            {
                double currAngle = vertexInx * partAngle;
                double currX =
                    cone.BaseRadius * Math.Cos(currAngle);
                double currZ =
                    cone.BaseRadius * Math.Sin(currAngle);

                // Set current body vertex.
                coneMesh.Positions.Add(new Point3D(
                    currX, cone.Height / -2, currZ));
                Vector3D bodyNormal = new Vector3D(
                    currX, bodyNormalY, currZ);
                bodyNormal.Normalize();
                coneMesh.Normals.Add(bodyNormal);

                // Set current base vertex.
                coneMesh.Positions.Add(new Point3D(
                    currX, cone.Height / -2, currZ));
                coneMesh.Normals.Add(
                    new Vector3D(0, -1, 0));

                // Set current body and base indices.
                if (vertexInx > 0)
                {
                    // Set current body index.
                    coneMesh.TriangleIndices.Add(0); // Top                    
                    coneMesh.TriangleIndices.Add(
                        (vertexInx + 1) * 2);
                    coneMesh.TriangleIndices.Add(
                        vertexInx * 2);

                    // Set current base index.
                    coneMesh.TriangleIndices.Add(1); // Base center                    
                    coneMesh.TriangleIndices.Add(
                        vertexInx * 2 + 1);
                    coneMesh.TriangleIndices.Add(
                        (vertexInx + 1) * 2 + 1);
                }
            }

            GeometryModel3D coneGeometry =
                new GeometryModel3D(
                    coneMesh, coneMaterial);

            // Set the world matrix
            Transform3DGroup transGroup =
                new Transform3DGroup();
            transGroup.Children.Add(
                new RotateTransform3D(
                    new AxisAngleRotation3D(
                        new Vector3D(1, 0, 0),
                        cone.RotationX)));
            transGroup.Children.Add(
                new RotateTransform3D(
                    new AxisAngleRotation3D(
                        new Vector3D(0, 0, 1),
                        cone.RotationZ)));
            transGroup.Children.Add(
                new TranslateTransform3D(
                    cone.CenterPosition.X,
                    cone.CenterPosition.Y,
                    cone.CenterPosition.Z));

            // Render the cone
            ModelVisual3D coneModel =
                new ModelVisual3D
                {
                    Content = coneGeometry,
                    Transform = transGroup
                };
            viewport3d.Children.Add(coneModel);
        }

    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions