Click here to Skip to main content
15,886,056 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 34K   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.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using MdxWpfInteroperability;

namespace MdxWpfInteroperability.Example
{
    public static class MdxSceneRenderer
    {
        public static void MdxRenderScene(SceneData scene,
            D3dHost mdxHost)
        {
            if (scene == null || mdxHost == null)
            {
                return;
            }

            mdxHost.BeginDrawing();

            Device device = mdxHost.D3dDevice;

            device.RenderState.ZBufferEnable = true;
            device.RenderState.Lighting = true;

            device.Clear(
                ClearFlags.Target |
                    ClearFlags.ZBuffer,
                    Color.White, 1.0f, 0);

            // Init camera matrices
            device.Transform.View =
                Matrix.LookAtLH(new Vector3(
                        (float)scene.CameraPosition.X,
                        (float)scene.CameraPosition.Y,
                        (float)scene.CameraPosition.Z),
                    new Vector3(0.0f, 0.0f, 0.0f),
                    new Vector3(0.0f, 1.0f, 0.0f));
            device.Transform.Projection =
                Matrix.PerspectiveFovLH(
                    (float)Math.PI / 4.0f, 1.0f, 1.0f,
                    (float)scene.FarPlaneDistance);

            // Add directional light
            device.Lights[0].Type =
                LightType.Directional;
            device.Lights[0].Diffuse = Color.White;
            device.Lights[0].Direction =
                Vector3.Normalize(
                    new Vector3(-1, -1, -1));
            device.Lights[0].Enabled = true;

            device.BeginScene();

            foreach (ConeData cone in scene.Cones)
            {
                MdxRenderCone(cone, device);
            }

            device.EndScene();

            mdxHost.EndDrawing();
        }

        private static void MdxRenderCone(ConeData cone,
            Device device)
        {
            float coneHeight = (float)cone.Height;
            float coneBaseRadius =
                (float)cone.BaseRadius;

            // Create the cone's material
            Color col = Color.FromArgb(
                ColorToInt(cone.MaterialColor));
            Material mtrl = new Material();
            mtrl.Diffuse = col;
            device.Material = mtrl;

            // 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.
            CustomVertex.PositionNormal[] bodyVertices =
                new CustomVertex.PositionNormal[
                    numOfPoints + 2];
            CustomVertex.PositionNormal[] baseVertices =
                new CustomVertex.PositionNormal[
                    numOfPoints + 2];

            // Set the top vertex.
            bodyVertices[0].Position =
                new Vector3(0, coneHeight / 2, 0);
            bodyVertices[0].Normal =
                new Vector3(0, 1, 0);

            // Set the base center vertex.
            baseVertices[0].Position =
                new Vector3(0, coneHeight / -2, 0);
            baseVertices[0].Normal =
                new Vector3(0, -1, 0);

            float bodyNormalY =
                (float)(Math.Sin(Math.PI -
                    Math.Atan(coneHeight /
                        coneBaseRadius) * 2) *
                Math.Sqrt(coneHeight * coneHeight +
                    coneBaseRadius * coneBaseRadius));

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

                // Set current body vertex.
                bodyVertices[numOfPoints + 1 - vertexInx].Position =
                    new Vector3(
                        currX, coneHeight / -2, currZ);
                bodyVertices[numOfPoints + 1 - vertexInx].Normal =
                    Vector3.Normalize(new Vector3(
                        currX, bodyNormalY, currZ));

                // Set current base vertex.
                baseVertices[vertexInx + 1].Position =
                    new Vector3(
                        currX, coneHeight / -2, currZ);
                baseVertices[vertexInx + 1].Normal =
                    new Vector3(0, -1, 0);
            }

            // Set the world matrix
            float rotateXRadians =
                (float)(cone.RotationX / 180 * Math.PI);
            float rotateZRadians =
                (float)(cone.RotationZ / 180 * Math.PI);
            device.Transform.World =
                Matrix.RotationX(rotateXRadians) *
                Matrix.RotationZ(rotateZRadians) *
                Matrix.Translation(new Vector3(
                    (float)cone.CenterPosition.X,
                    (float)cone.CenterPosition.Y,
                    (float)cone.CenterPosition.Z));

            // Render the cone
            device.VertexFormat =
                CustomVertex.PositionNormal.Format;
            device.DrawUserPrimitives(
                PrimitiveType.TriangleFan,
                numOfPoints, bodyVertices);
            device.DrawUserPrimitives(
                PrimitiveType.TriangleFan,
                numOfPoints, baseVertices);
        }

        private static int ColorToInt(
            System.Windows.Media.Color color)
        {
            return (int)color.A << 24 |
                (int)color.R << 16 |
                (int)color.G << 8 |
                (int)color.B;
        }

    }
}

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