-
-
Notifications
You must be signed in to change notification settings - Fork 911
/
SortModeDistance.cs
64 lines (51 loc) · 2.56 KB
/
SortModeDistance.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// Copyright (c) Stride contributors (https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using Stride.Core.Mathematics;
namespace Stride.Rendering
{
/// <summary>
/// Helper class to sort objects based on distance.
/// </summary>
public abstract class SortModeDistance : SortMode
{
private bool reverseDistance;
protected int distancePosition = 32;
protected int distancePrecision = 16;
protected int statePosition = 0;
protected int statePrecision = 32;
protected SortModeDistance(bool reverseDistance)
{
this.reverseDistance = reverseDistance;
}
public static unsafe uint ComputeDistance(float distance)
{
// Compute uint sort key (http://aras-p.info/blog/2014/01/16/rough-sorting-by-depth/)
var distanceI = *((uint*)&distance);
return ((uint)(-(int)(distanceI >> 31)) | 0x80000000) ^ distanceI;
}
public static SortKey CreateSortKey(float distance)
{
var distanceI = ComputeDistance(distance);
return new SortKey { Value = distanceI };
}
public override unsafe void GenerateSortKey(RenderView renderView, RenderViewStage renderViewStage, SortKey* sortKeys)
{
Matrix.Invert(ref renderView.View, out var viewInverse);
var plane = new Plane(viewInverse.Forward, Vector3.Dot(viewInverse.TranslationVector, viewInverse.Forward)); // TODO: Point-normal-constructor seems wrong. Check.
var renderNodes = renderViewStage.RenderNodes;
int distanceShift = 32 - distancePrecision;
int stateShift = 32 - statePrecision;
for (int i = 0; i < renderNodes.Count; ++i)
{
var renderNode = renderNodes[i];
var renderObject = renderNode.RenderObject;
var distance = CollisionHelper.DistancePlanePoint(ref plane, ref renderObject.BoundingBox.Center);
var distanceI = ComputeDistance(distance);
if (reverseDistance)
distanceI = ~distanceI;
// Compute sort key
sortKeys[i] = new SortKey { Value = ((ulong)renderNode.RootRenderFeature.SortKey << 56) | ((ulong)(distanceI >> distanceShift) << distancePosition) | ((ulong)(renderObject.StateSortKey >> stateShift) << statePosition), Index = i, StableIndex = renderObject.Index };
}
}
}
}