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