forked from CartBlanche/MonoGame-Samples
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added missing file. CollisionSample still doesn't run due to unimplem…
…ented BoundFrustrum API.
- Loading branch information
Dominique Louis
committed
Jun 24, 2012
1 parent
c60b3da
commit edc7f91
Showing
2 changed files
with
357 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,335 @@ | ||
//----------------------------------------------------------------------------- | ||
// DebugDraw.cs | ||
// | ||
// Microsoft XNA Community Game Platform | ||
// Copyright (C) Microsoft Corporation. All rights reserved. | ||
//----------------------------------------------------------------------------- | ||
|
||
using System; | ||
using System.Diagnostics; | ||
using System.Collections.Generic; | ||
using Microsoft.Xna.Framework; | ||
using Microsoft.Xna.Framework.Graphics; | ||
|
||
|
||
namespace CollisionSample | ||
{ | ||
/// <summary> | ||
/// Debug drawing routines for common collision shapes. These are not designed to be the most | ||
/// efficent way to submit geometry to the graphics device as they are intended for use in | ||
/// visualizing collision for debugging purposes. | ||
/// </summary> | ||
public class DebugDraw : IDisposable | ||
{ | ||
#region Constants | ||
|
||
public const int MAX_VERTS = 2000; | ||
public const int MAX_INDICES = 2000; | ||
|
||
// Indices for drawing the edges of a cube, given the vertex ordering | ||
// used by Bounding(Frustum|Box|OrientedBox).GetCorners() | ||
static ushort[] cubeIndices = new ushort[] { 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 }; | ||
|
||
#endregion | ||
|
||
#region Fields | ||
|
||
BasicEffect basicEffect; | ||
DynamicVertexBuffer vertexBuffer; | ||
DynamicIndexBuffer indexBuffer; | ||
|
||
ushort[] Indices = new ushort[MAX_INDICES]; | ||
VertexPositionColor[] Vertices = new VertexPositionColor[MAX_VERTS]; | ||
int IndexCount; | ||
int VertexCount; | ||
|
||
#endregion | ||
|
||
#region Initialization | ||
|
||
public DebugDraw(GraphicsDevice device) | ||
{ | ||
vertexBuffer = new DynamicVertexBuffer(device, typeof(VertexPositionColor), MAX_VERTS, BufferUsage.WriteOnly); | ||
indexBuffer = new DynamicIndexBuffer(device, typeof(ushort), MAX_INDICES, BufferUsage.WriteOnly); | ||
|
||
basicEffect = new BasicEffect(device); //(device, null); | ||
basicEffect.LightingEnabled = false; | ||
basicEffect.VertexColorEnabled = true; | ||
basicEffect.TextureEnabled = false; | ||
} | ||
|
||
#endregion | ||
|
||
#region Dispose | ||
|
||
~DebugDraw() | ||
{ | ||
Dispose(false); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
Dispose(true); | ||
GC.SuppressFinalize(this); | ||
} | ||
|
||
protected virtual void Dispose(bool disposing) | ||
{ | ||
if (disposing) | ||
{ | ||
if (vertexBuffer != null) | ||
vertexBuffer.Dispose(); | ||
|
||
if (indexBuffer != null) | ||
indexBuffer.Dispose(); | ||
|
||
if (basicEffect != null) | ||
basicEffect.Dispose(); | ||
} | ||
} | ||
|
||
#endregion | ||
|
||
#region Draw | ||
|
||
/// <summary> | ||
/// Starts debug drawing by setting the required render states and camera information | ||
/// </summary> | ||
public void Begin(Matrix view, Matrix projection) | ||
{ | ||
basicEffect.World = Matrix.Identity; | ||
basicEffect.View = view; | ||
basicEffect.Projection = projection; | ||
|
||
VertexCount = 0; | ||
IndexCount = 0; | ||
} | ||
|
||
/// <summary> | ||
/// Ends debug drawing and restores standard render states | ||
/// </summary> | ||
public void End() | ||
{ | ||
FlushDrawing(); | ||
} | ||
|
||
public void DrawWireShape(Vector3[] positionArray, ushort[] indexArray, Color color) | ||
{ | ||
if (Reserve(positionArray.Length, indexArray.Length)) | ||
{ | ||
for (int i = 0; i < indexArray.Length; i++) | ||
Indices[IndexCount++] = (ushort)(VertexCount + indexArray[i]); | ||
|
||
for (int i = 0; i < positionArray.Length; i++) | ||
Vertices[VertexCount++] = new VertexPositionColor(positionArray[i], color); | ||
} | ||
} | ||
|
||
// Draw any queued objects and reset our line buffers | ||
private void FlushDrawing() | ||
{ | ||
if (IndexCount > 0) | ||
{ | ||
vertexBuffer.SetData(Vertices, 0, VertexCount, SetDataOptions.Discard); | ||
indexBuffer.SetData(Indices, 0, IndexCount, SetDataOptions.Discard); | ||
|
||
GraphicsDevice device = basicEffect.GraphicsDevice; | ||
device.SetVertexBuffer(vertexBuffer); | ||
device.Indices = indexBuffer; | ||
|
||
foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) | ||
{ | ||
pass.Apply(); | ||
device.DrawIndexedPrimitives(PrimitiveType.LineList, 0, 0, VertexCount, 0, IndexCount / 2); | ||
} | ||
|
||
device.SetVertexBuffer(null); | ||
device.Indices = null; | ||
} | ||
IndexCount = 0; | ||
VertexCount = 0; | ||
} | ||
|
||
// Check if there's enough space to draw an object with the given vertex/index counts. | ||
// If necessary, call FlushDrawing() to make room. | ||
private bool Reserve(int numVerts, int numIndices) | ||
{ | ||
if(numVerts > MAX_VERTS || numIndices > MAX_INDICES) | ||
{ | ||
// Whatever it is, we can't draw it | ||
return false; | ||
} | ||
if (VertexCount + numVerts > MAX_VERTS || IndexCount + numIndices >= MAX_INDICES) | ||
{ | ||
// We can draw it, but we need to make room first | ||
FlushDrawing(); | ||
} | ||
return true; | ||
} | ||
|
||
/// <summary> | ||
/// Renders a 2D grid (must be called within a Begin/End pair) | ||
/// </summary> | ||
/// <param name="xAxis">Vector direction for the local X-axis direction of the grid</param> | ||
/// <param name="yAxis">Vector direction for the local Y-axis of the grid</param> | ||
/// <param name="origin">3D starting anchor point for the grid</param> | ||
/// <param name="iXDivisions">Number of divisions in the local X-axis direction</param> | ||
/// <param name="iYDivisions">Number of divisions in the local Y-axis direction</param> | ||
/// <param name="color">Color of the grid lines</param> | ||
public void DrawWireGrid(Vector3 xAxis, Vector3 yAxis, Vector3 origin, int iXDivisions, int iYDivisions, Color color) | ||
{ | ||
Vector3 pos, step; | ||
|
||
pos = origin; | ||
step = xAxis / iXDivisions; | ||
for (int i = 0; i <= iXDivisions; i++) | ||
{ | ||
DrawLine(pos, pos + yAxis, color); | ||
pos += step; | ||
} | ||
|
||
pos = origin; | ||
step = yAxis / iYDivisions; | ||
for (int i = 0; i <= iYDivisions; i++) | ||
{ | ||
DrawLine(pos, pos + xAxis, color); | ||
pos += step; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Renders the outline of a bounding frustum | ||
/// </summary> | ||
/// <param name="frustum">Bounding frustum to render</param> | ||
/// <param name="color">Color of the frustum lines</param> | ||
public void DrawWireFrustum(BoundingFrustum frustum, Color color) | ||
{ | ||
DrawWireShape(frustum.GetCorners(), cubeIndices, color); | ||
} | ||
|
||
/// <summary> | ||
/// Renders the outline of an axis-aligned bounding box | ||
/// </summary> | ||
/// <param name="box">Bounding box to render</param> | ||
/// <param name="color">Color of the box lines</param> | ||
public void DrawWireBox(BoundingBox box, Color color) | ||
{ | ||
DrawWireShape(box.GetCorners(), cubeIndices, color); | ||
} | ||
|
||
/// <summary> | ||
/// Renders the outline of an oriented bounding box | ||
/// </summary> | ||
/// <param name="box">Oriented bounding box to render</param> | ||
/// <param name="color">Color of the box lines</param> | ||
public void DrawWireBox(BoundingOrientedBox box, Color color) | ||
{ | ||
DrawWireShape(box.GetCorners(), cubeIndices, color); | ||
} | ||
|
||
/// <summary> | ||
/// Renders a circular ring (tessellated circle) | ||
/// </summary> | ||
/// <param name="origin">Center point for the ring</param> | ||
/// <param name="majorAxis">Direction of the major-axis of the circle</param> | ||
/// <param name="minorAxis">Direction of hte minor-axis of the circle</param> | ||
/// <param name="color">Color of the ring lines</param> | ||
public void DrawRing(Vector3 origin, Vector3 majorAxis, Vector3 minorAxis, Color color) | ||
{ | ||
const int RING_SEGMENTS = 32; | ||
const float fAngleDelta = 2.0F * (float)Math.PI / RING_SEGMENTS; | ||
|
||
if (Reserve(RING_SEGMENTS, RING_SEGMENTS * 2)) | ||
{ | ||
for (int i = 0; i < RING_SEGMENTS; i++) | ||
{ | ||
Indices[IndexCount++] = (ushort)(VertexCount + i); | ||
Indices[IndexCount++] = (ushort)(VertexCount + (i + 1) % RING_SEGMENTS); | ||
} | ||
float cosDelta = (float)Math.Cos(fAngleDelta); | ||
float sinDelta = (float)Math.Sin(fAngleDelta); | ||
|
||
float cosAcc = 1; | ||
float sinAcc = 0; | ||
|
||
for (int i = 0; i < RING_SEGMENTS; ++i) | ||
{ | ||
Vector3 pos = new Vector3(majorAxis.X * cosAcc + minorAxis.X * sinAcc + origin.X, | ||
majorAxis.Y * cosAcc + minorAxis.Y * sinAcc + origin.Y, | ||
majorAxis.Z * cosAcc + minorAxis.Z * sinAcc + origin.Z); | ||
|
||
Vertices[VertexCount++] = new VertexPositionColor(pos, color); | ||
|
||
float newCos = cosAcc * cosDelta - sinAcc * sinDelta; | ||
float newSin = cosAcc * sinDelta + sinAcc * cosDelta; | ||
|
||
cosAcc = newCos; | ||
sinAcc = newSin; | ||
} | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Renders the outline of a bounding sphere. | ||
/// | ||
/// This code assumes that the model and view matrices contain only rigid motion. | ||
/// </summary> | ||
/// <param name="sphere">Bounding sphere to render</param> | ||
/// <param name="color">Color of the outline lines</param> | ||
public void DrawWireSphere(BoundingSphere sphere, Color color) | ||
{ | ||
// Invert the modelview matrix to get direction vectors | ||
// in screen space, so we can draw a circle that always | ||
// faces the camera. | ||
Matrix view = basicEffect.World * basicEffect.View; | ||
Matrix.Transpose(ref view, out view); | ||
DrawRing(sphere.Center, view.Right * sphere.Radius, view.Up * sphere.Radius, color); | ||
} | ||
|
||
/// <summary> | ||
/// Draw a ray of the given length | ||
/// </summary> | ||
/// <param name="ray"></param> | ||
/// <param name="color"></param> | ||
/// <param name="length"></param> | ||
public void DrawRay(Ray ray, Color color, float length) | ||
{ | ||
DrawLine(ray.Position, ray.Position + ray.Direction * length, color); | ||
} | ||
|
||
public void DrawLine(Vector3 v0, Vector3 v1, Color color) | ||
{ | ||
if(Reserve(2, 2)) | ||
{ | ||
Indices[IndexCount++] = (ushort)VertexCount; | ||
Indices[IndexCount++] = (ushort)(VertexCount+1); | ||
Vertices[VertexCount++] = new VertexPositionColor(v0, color); | ||
Vertices[VertexCount++] = new VertexPositionColor(v1, color); | ||
} | ||
} | ||
|
||
public void DrawWireTriangle(Vector3 v0, Vector3 v1, Vector3 v2, Color color) | ||
{ | ||
if(Reserve(3, 6)) | ||
{ | ||
Indices[IndexCount++] = (ushort)(VertexCount+0); | ||
Indices[IndexCount++] = (ushort)(VertexCount+1); | ||
Indices[IndexCount++] = (ushort)(VertexCount+1); | ||
Indices[IndexCount++] = (ushort)(VertexCount+2); | ||
Indices[IndexCount++] = (ushort)(VertexCount+2); | ||
Indices[IndexCount++] = (ushort)(VertexCount+0); | ||
|
||
Vertices[VertexCount++] = new VertexPositionColor(v0, color); | ||
Vertices[VertexCount++] = new VertexPositionColor(v1, color); | ||
Vertices[VertexCount++] = new VertexPositionColor(v2, color); | ||
} | ||
} | ||
|
||
public void DrawWireTriangle(Triangle t, Color color) | ||
{ | ||
DrawWireTriangle(t.V0, t.V1, t.V2, color); | ||
} | ||
|
||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters