port from perforce
This commit is contained in:
106
aiwaz/Aiwaz.Resources/PickHull.cs
Normal file
106
aiwaz/Aiwaz.Resources/PickHull.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Aiwaz.Contracts;
|
||||
using SlimDX;
|
||||
|
||||
namespace Aiwaz.Resources
|
||||
{
|
||||
public class PickHull : IPickHull
|
||||
{
|
||||
private VertexElement positionElement;
|
||||
private int strideToPosition;
|
||||
|
||||
private DataStream vertexData;
|
||||
private int vertexCount;
|
||||
private VertexElement[] vertexElements;
|
||||
private int vertexElementSize;
|
||||
|
||||
private DataStream indexData;
|
||||
private int indexCount;
|
||||
|
||||
private Vector3 boxMaxVector;
|
||||
private Vector3 boxMinVector;
|
||||
|
||||
public PickHull(DataStream vertexData, int vertexCount, VertexElement[] vertexElements, DataStream indexData, int indexCount)
|
||||
{
|
||||
this.vertexData = vertexData;
|
||||
this.vertexCount = vertexCount;
|
||||
this.vertexElements = vertexElements;
|
||||
this.indexData = indexData;
|
||||
this.indexCount = indexCount;
|
||||
|
||||
this.vertexElementSize = (int)vertexData.Length / vertexCount;
|
||||
|
||||
this.positionElement = vertexElements.First(e => e.WellKnownFormat == VertexElement.Format.Position);
|
||||
foreach (var element in vertexElements)
|
||||
{
|
||||
if (!element.Equals(positionElement))
|
||||
strideToPosition += element.Size;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
this.Precalculate();
|
||||
}
|
||||
|
||||
public bool TryPick(Ray pickRay, Matrix worldMatrix, out float distance)
|
||||
{
|
||||
distance = float.MaxValue;
|
||||
|
||||
var boundingSphere = CalcBoundingSphere(worldMatrix);
|
||||
if (!Ray.Intersects(pickRay, boundingSphere, out distance))
|
||||
return false;
|
||||
|
||||
distance = float.MaxValue;
|
||||
indexData.Position = 0;
|
||||
for (var i = 0; i < indexCount / 3; ++i)
|
||||
{
|
||||
var triangle = new Vector3[3];
|
||||
triangle[0] = Vector3.TransformCoordinate(this.GetPositionFromData(indexData.Read<uint>()), worldMatrix);
|
||||
triangle[1] = Vector3.TransformCoordinate(this.GetPositionFromData(indexData.Read<uint>()), worldMatrix);
|
||||
triangle[2] = Vector3.TransformCoordinate(this.GetPositionFromData(indexData.Read<uint>()), worldMatrix);
|
||||
|
||||
float newDistance;
|
||||
if (!Ray.Intersects(pickRay, triangle[0], triangle[1], triangle[2], out newDistance)
|
||||
|| newDistance > distance)
|
||||
continue;
|
||||
distance = newDistance;
|
||||
}
|
||||
|
||||
return distance != float.MaxValue;
|
||||
}
|
||||
|
||||
private Vector3 GetPositionFromData(uint index)
|
||||
{
|
||||
vertexData.Position = index * vertexElementSize + strideToPosition;
|
||||
return vertexData.Read<Vector3>();
|
||||
}
|
||||
|
||||
protected void Precalculate()
|
||||
{
|
||||
boxMinVector = Vector3.Zero;
|
||||
boxMaxVector = Vector3.Zero;
|
||||
for (uint i = 0; i < vertexCount; ++i)
|
||||
{
|
||||
boxMinVector = i == 0 ? this.GetPositionFromData(i) : Vector3.Maximize(boxMinVector, this.GetPositionFromData(i));
|
||||
boxMaxVector = i == 0 ? this.GetPositionFromData(i) : Vector3.Minimize(boxMaxVector, this.GetPositionFromData(i));
|
||||
}
|
||||
}
|
||||
|
||||
public BoundingSphere CalcBoundingSphere(Matrix worldMatrix)
|
||||
{
|
||||
var centerPosition = Vector3.TransformCoordinate(Vector3.Zero, worldMatrix);
|
||||
var maxVec = Vector3.TransformCoordinate(boxMaxVector, worldMatrix);
|
||||
return new BoundingSphere(centerPosition, maxVec.Length());
|
||||
}
|
||||
|
||||
public BoundingBox CalcBoundingBox(Matrix worldMatrix)
|
||||
{
|
||||
var minVec = Vector3.TransformCoordinate(boxMinVector, worldMatrix);
|
||||
var maxVec = Vector3.TransformCoordinate(boxMaxVector, worldMatrix);
|
||||
return new BoundingBox(minVec, maxVec);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user