Last active
April 10, 2020 22:26
-
-
Save HurricanKai/0d74787b47d8e221911c0b3442bda788 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
public static class HERO | |
{ | |
public static bool Intersects(Ray ray, Octree octree) | |
{ | |
var (sumin, slmax) = CalculateBounds(ray, octree); | |
return slmax < sumin; | |
} | |
public static int? Raytrace(Ray ray, Octree octree) | |
{ | |
var (sumin, slmax) = CalculateBounds(ray, octree); | |
if (!(slmax < sumin)) | |
return null; | |
return Search(ray, octree, slmax, sumin); | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
private static (float, float) CalculateBounds(Ray ray, Octree octree) | |
{ | |
var min = (Vector3) octree.Offset; | |
var max = (Vector3) octree.Offset + octree.Extends; | |
var E = ray.Origin; | |
var v = ray.Direction; | |
var vsignz = !(v.Z < 0); | |
var vsigny = !(v.Y < 0); | |
var vsignx = !(v.X < 0); | |
var sxmin = (min.X - E.X) / v.X; | |
var symin = (min.Y - E.Y) / v.Y; | |
var szmin = (min.Z - E.Z) / v.Z; | |
var sxmax = (max.X - E.X) / v.X; | |
var symax = (max.Y - E.Y) / v.Y; | |
var szmax = (max.Z - E.Z) / v.Z; | |
var lowerx = vsignx ? sxmin : sxmax; | |
var lowery = vsigny ? symin : symax; | |
var lowerz = vsignz ? szmin : szmax; | |
var upperx = vsignx ? sxmax : sxmin; | |
var uppery = vsigny ? symax : symin; | |
var upperz = vsignz ? szmax : szmin; | |
var slmax = MathF.Max(lowerx, MathF.Max(lowery, lowerz)); | |
var sumin = MathF.Min(upperx, MathF.Min(uppery, upperz)); | |
return (sumin, slmax); | |
} | |
private static int? Search(Ray ray, Octree octree, float slmax, float sumin) | |
{ | |
if (octree.Value != null) | |
return octree.Value; | |
var E = ray.Origin; | |
var v = ray.Direction; | |
var vsignz = v.Z < 0; | |
var vsigny = v.Y < 0; | |
var vsignx = v.X < 0; | |
var VMASK = (byte)( | |
((byte) (vsignz ? 1 : 0) << 2) | | |
((byte) (vsigny ? 1 : 0) << 1) | | |
((byte) (vsignx ? 1 : 0) << 0)); | |
var mid = octree.Offset + ((Vector3) octree.Extends / 2); | |
var sxmid = (mid.X - E.X) / v.X; | |
var symid = (mid.Y - E.Y) / v.Y; | |
var szmid = (mid.Z - E.Z) / v.Z; | |
var CHILDMASK = (byte) ( | |
((byte) (szmid < slmax ? 1 : 0) << 2) | | |
((byte) (symid < slmax ? 1 : 0) << 1) | | |
((byte) (sxmid < slmax ? 1 : 0) << 0)); | |
var LASTMASK = (byte) ( | |
((byte) (szmid < sumin ? 1 : 0) << 2) | | |
((byte) (symid < sumin ? 1 : 0) << 1) | | |
((byte) (sxmid < sumin ? 1 : 0) << 0)); | |
var a = (byte) (sxmid < symid ? 1 : 0); | |
var b = (byte) (sxmid < szmid ? 1 : 0); | |
var c = (byte) (symid < szmid ? 1 : 0); | |
var na = (byte)(~a & 0b1); | |
var nb = (byte)(~b & 0b1); | |
var nc = (byte)(~c & 0b1); | |
Span<byte> MASKLIST = stackalloc byte[3]; | |
MASKLIST[0] = (byte) ( | |
(((b | nc) & 0b1) << 2) | | |
(((na & c) & 0b1) << 1) | | |
(((a & b) & 0b1) << 0) | |
); | |
MASKLIST[1] = (byte) ( | |
(((b ^ c) & 0b1) << 2) | | |
(((byte) ~(a ^ c) & 0b1) << 1) | | |
(((a ^ b) & 0b1) << 0) | |
); | |
MASKLIST[2] = (byte) ( | |
(((b & c) & 0b1) << 2) | | |
(((a & nc) & 0b1) << 1) | | |
(((a | nb) & 0b1) << 0) | |
); | |
var i = 0; | |
var children = octree.Children.Span; | |
while (true) | |
{ | |
var child = children[CHILDMASK ^ VMASK]; | |
var (csumin, cslmax) = CalculateBounds(ray, child); | |
var res = Search(ray, child, cslmax, csumin); | |
if (res != null && res.Value != 0) | |
return res.Value; | |
if (CHILDMASK == LASTMASK) | |
break; | |
while ((MASKLIST[i] & CHILDMASK) != 0) | |
i++; | |
CHILDMASK |= MASKLIST[i]; | |
} | |
return 0; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment