|
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using MdxScene.Cameras;
using MdxScene.Lights;
using MdxScene.Shapes;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.Threading.Tasks;
namespace MdxScene
{
public class D3dScene
{
public D3dScene()
{
ClearColor = Color.Black;
RenderShapesParallelly = false;
}
public virtual void Render(Device d3dDevice)
{
if (null == d3dDevice)
{
return;
}
InitDevice(d3dDevice);
d3dDevice.BeginScene();
// Render camera
RenderCamera(d3dDevice);
// Render lights
RenderLights(d3dDevice);
// Render shapes
RenderShapes(d3dDevice);
d3dDevice.EndScene();
}
protected virtual void InitDevice(Device d3dDevice)
{
d3dDevice.RenderState.ZBufferEnable = true;
d3dDevice.RenderState.Lighting = Lights.Count > 0;
d3dDevice.RenderState.CullMode = Camera.CoordinateSystem == CameraCoordinateSystem.RightHanded
? Cull.Clockwise
: Cull.CounterClockwise;
d3dDevice.RenderState.NormalizeNormals = true;
d3dDevice.RenderState.DiffuseMaterialSource = ColorSource.Material;
d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, ClearColor, 1.0f, 0);
}
protected virtual void RenderCamera(Device d3dDevice)
{
Camera.Render(d3dDevice);
}
protected virtual void RenderLights(Device d3dDevice)
{
// Disable old scene lights.
int lightsCount = d3dDevice.Lights.Count;
for (int oldLightInx=0; oldLightInx<lightsCount; oldLightInx++)
{
d3dDevice.Lights[oldLightInx].Enabled = false;
}
// Render the enabled scene lights.
int lightIndex = 0;
foreach (D3dLight light in Lights)
{
if (null != light && light.Enabled)
{
light.Index = lightIndex;
light.Render(d3dDevice);
lightIndex++;
}
}
}
protected virtual void RenderShapes(Device d3dDevice)
{
ShapeEnvironmentData environmentData = GetShapeEnvironmentData();
if (RenderShapesParallelly)
{
Parallel.ForEach(Shapes, s => RenderShape(s, environmentData, d3dDevice));
}
else
{
Shapes.ForEach(s => RenderShape(s, environmentData, d3dDevice));
}
}
protected virtual ShapeEnvironmentData GetShapeEnvironmentData()
{
return new ShapeEnvironmentData
{
ViewMatrix = Camera.ViewMatrix,
ProjectionMatrix = Camera.ProjectionMatrix
};
}
protected virtual void RenderShape(D3dShape shape, ShapeEnvironmentData environmentData, Device d3dDevice)
{
if (null == shape)
{
return;
}
shape.RenderAlsoIfOutOfView = RenderShapesAlsoIfOutOfView;
shape.EnvironmentData = environmentData;
shape.Render(d3dDevice);
}
public D3dShape Pick(Device d3dDevice, float surfaceX, float surfaceY)
{
LastPickIntersections = GetPointIntersections(d3dDevice, surfaceX, surfaceY);
// Get the closest shape.
D3dShape res = GetLastPickClosestShape();
// Get the pickable parent of the shape.
while (null != res && !res.IsPickable)
{
res = res.Parent;
}
return res;
}
public List<IntersectResult> GetPointIntersections(Device d3dDevice, float surfaceX, float surfaceY)
{
Vector3 nearPlanePoint = new Vector3(surfaceX, surfaceY, 0);
Vector3 farPlanePoint = new Vector3(surfaceX, surfaceY, 1);
nearPlanePoint.Unproject(d3dDevice.Viewport, d3dDevice.Transform.Projection, d3dDevice.Transform.View,
Matrix.Identity);
farPlanePoint.Unproject(d3dDevice.Viewport, d3dDevice.Transform.Projection, d3dDevice.Transform.View,
Matrix.Identity);
Vector3 rayDirection = Vector3.Subtract(farPlanePoint, nearPlanePoint);
List<IntersectResult> res = new List<IntersectResult>();
Parallel.ForEach(Shapes, shape => shape.AddRayIntersections(nearPlanePoint, rayDirection, res));
return res;
}
public D3dShape GetLastPickClosestShape()
{
return LastPickIntersections.OrderBy(ir => ir.TriangleIntersections.Min(ti => ti.Dist)).
Select(ir => ir.Shape).FirstOrDefault();
}
public void AdjustCameraView(bool keepAspectRatio = true)
{
Camera.AdjustView(Shapes.Where(s => s.IsVisible), keepAspectRatio);
}
#region Properties
#region Camera
private D3dCamera _camera;
public D3dCamera Camera
{
get { return _camera ?? (_camera = new D3dPerspectiveFovCamera()); }
set { _camera = value; }
}
#endregion
#region Lights
private List<D3dLight> _lights;
public List<D3dLight> Lights
{
get { return _lights ?? (_lights = new List<D3dLight>()); }
}
#endregion
#region Shapes
private List<D3dShape> _shapes;
public List<D3dShape> Shapes
{
get { return _shapes ?? (_shapes = new List<D3dShape>()); }
}
#endregion
public Color ClearColor { get; set; }
#region LastPickIntersections
private List<IntersectResult> _lastPickIntersections;
public List<IntersectResult> LastPickIntersections
{
get { return _lastPickIntersections ?? (_lastPickIntersections = new List<IntersectResult>()); }
protected set { _lastPickIntersections = value; }
}
#endregion
public bool RenderShapesParallelly { get; set; }
public bool RenderShapesAlsoIfOutOfView { get; set; }
#endregion
}
}
|
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.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.