mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-11 08:36:38 -04:00
Replace ray-triangle intersection with much faster alternative.
This commit is contained in:
parent
c22874d4fc
commit
ba9d29b4cd
@ -131,8 +131,7 @@ namespace ClassicalSharp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( right ) {
|
if( right ) {
|
||||||
if( SelectedPos.TranslatedPos == null ) return;
|
Vector3I pos = SelectedPos.TranslatedPos;
|
||||||
Vector3I pos = SelectedPos.TranslatedPos.Value;
|
|
||||||
Block block = HeldBlock;
|
Block block = HeldBlock;
|
||||||
byte oldBlock = 0;
|
byte oldBlock = 0;
|
||||||
|
|
||||||
|
@ -4,44 +4,12 @@ using OpenTK;
|
|||||||
|
|
||||||
namespace ClassicalSharp {
|
namespace ClassicalSharp {
|
||||||
|
|
||||||
public struct Quad {
|
|
||||||
public Vector3 Normal;
|
|
||||||
public Vector3 Pos1, Pos2, Pos3, Pos4;
|
|
||||||
|
|
||||||
public Quad( Vector3 norm, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4 ) {
|
|
||||||
Pos1 = p1;
|
|
||||||
Pos2 = p2;
|
|
||||||
Pos3 = p3;
|
|
||||||
Pos4 = p4;
|
|
||||||
Normal = norm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class IntersectionUtils {
|
public static class IntersectionUtils {
|
||||||
|
|
||||||
public static IEnumerable<Quad> GetFaces( Vector3 min, Vector3 max ) {
|
|
||||||
yield return new Quad( -Vector3.UnitY, // bottom
|
|
||||||
new Vector3( min.X, min.Y, min.Z ), new Vector3( max.X, min.Y, min.Z ),
|
|
||||||
new Vector3( max.X, min.Y, max.Z ), new Vector3( min.X, min.Y, max.Z ) );
|
|
||||||
yield return new Quad( Vector3.UnitY, // top
|
|
||||||
new Vector3( min.X, max.Y, min.Z ), new Vector3( max.X, max.Y, min.Z ),
|
|
||||||
new Vector3( max.X, max.Y, max.Z ), new Vector3( min.X, max.Y, max.Z ) );
|
|
||||||
yield return new Quad( -Vector3.UnitX, // left
|
|
||||||
new Vector3( min.X, min.Y, min.Z ), new Vector3( min.X, max.Y, min.Z ),
|
|
||||||
new Vector3( min.X, max.Y, max.Z ), new Vector3( min.X, min.Y, max.Z ) );
|
|
||||||
yield return new Quad( Vector3.UnitX, // right
|
|
||||||
new Vector3( max.X, min.Y, min.Z ), new Vector3( max.X, max.Y, min.Z ),
|
|
||||||
new Vector3( max.X, max.Y, max.Z ), new Vector3( max.X, min.Y, max.Z ) );
|
|
||||||
yield return new Quad( -Vector3.UnitZ, // front
|
|
||||||
new Vector3( min.X, min.Y, min.Z ), new Vector3( max.X, min.Y, min.Z ),
|
|
||||||
new Vector3( max.X, max.Y, min.Z ), new Vector3( min.X, max.Y, min.Z ) );
|
|
||||||
yield return new Quad( Vector3.UnitZ, // back
|
|
||||||
new Vector3( min.X, min.Y, max.Z ), new Vector3( max.X, min.Y, max.Z ),
|
|
||||||
new Vector3( max.X, max.Y, max.Z ), new Vector3( min.X, max.Y, max.Z ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//http://www.cs.utah.edu/~awilliam/box/box.pdf
|
//http://www.cs.utah.edu/~awilliam/box/box.pdf
|
||||||
public static bool RayIntersectsBox( Vector3 origin, Vector3 dir, Vector3 min, Vector3 max ) {
|
public static bool RayIntersectsBox( Vector3 origin, Vector3 dir, Vector3 min, Vector3 max,
|
||||||
|
out float t0, out float t1 ) {
|
||||||
|
t0 = t1 = 0;
|
||||||
float tmin, tmax, tymin, tymax, tzmin, tzmax;
|
float tmin, tmax, tymin, tymax, tzmin, tzmax;
|
||||||
float invDirX = 1 / dir.X;
|
float invDirX = 1 / dir.X;
|
||||||
if( invDirX >= 0 ) {
|
if( invDirX >= 0 ) {
|
||||||
@ -77,10 +45,16 @@ namespace ClassicalSharp {
|
|||||||
}
|
}
|
||||||
if( tmin > tzmax || tzmin > tmax )
|
if( tmin > tzmax || tzmin > tmax )
|
||||||
return false;
|
return false;
|
||||||
|
if( tzmin > tmin )
|
||||||
|
tmin = tzmin;
|
||||||
|
if( tzmax < tmax )
|
||||||
|
tmax = tzmax;
|
||||||
|
t0 = tmin;
|
||||||
|
t1 = tmax;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/raytri/raytri.c
|
//http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/raytri/raytri.c
|
||||||
public static bool RayTriangleIntersect( Vector3 orig, Vector3 dir, Vector3 p0, Vector3 p1, Vector3 p2, out Vector3 I ) {
|
public static bool RayTriangleIntersect( Vector3 orig, Vector3 dir, Vector3 p0, Vector3 p1, Vector3 p2, out Vector3 I ) {
|
||||||
Vector3 edge1 = p1 - p0;
|
Vector3 edge1 = p1 - p0;
|
||||||
Vector3 edge2 = p2 - p0;
|
Vector3 edge2 = p2 - p0;
|
||||||
|
@ -32,8 +32,9 @@ namespace ClassicalSharp {
|
|||||||
float height = info.BlockHeight( block );
|
float height = info.BlockHeight( block );
|
||||||
Vector3 min = new Vector3( x, y, z );
|
Vector3 min = new Vector3( x, y, z );
|
||||||
Vector3 max = new Vector3( x + 1, y + height, z + 1 );
|
Vector3 max = new Vector3( x + 1, y + height, z + 1 );
|
||||||
if( IntersectionUtils.RayIntersectsBox( origin, dir, min, max ) ) {
|
float t0, t1;
|
||||||
return new PickedPos( min, max, origin, dir );
|
if( IntersectionUtils.RayIntersectsBox( origin, dir, min, max, out t0, out t1 ) ) {
|
||||||
|
return new PickedPos( min, max, origin, dir, t0, t1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,54 +124,30 @@ namespace ClassicalSharp {
|
|||||||
|
|
||||||
public Vector3 Min, Max;
|
public Vector3 Min, Max;
|
||||||
public Vector3I BlockPos;
|
public Vector3I BlockPos;
|
||||||
public Vector3I? TranslatedPos;
|
public Vector3I TranslatedPos;
|
||||||
|
|
||||||
struct QuadIntersection {
|
public PickedPos( Vector3 p1, Vector3 p2, Vector3 origin, Vector3 dir, float t0, float t1 ) {
|
||||||
public Quad Quad;
|
|
||||||
public Vector3 Intersection;
|
|
||||||
|
|
||||||
public QuadIntersection( Quad quad, Vector3 intersection ) {
|
|
||||||
Quad = quad;
|
|
||||||
Intersection = intersection;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PickedPos( Vector3 p1, Vector3 p2, Vector3 origin, Vector3 dir ) {
|
|
||||||
Min = Vector3.Min( p1, p2 );
|
Min = Vector3.Min( p1, p2 );
|
||||||
Max = Vector3.Max( p1, p2 );
|
Max = Vector3.Max( p1, p2 );
|
||||||
BlockPos = Vector3I.Truncate( Min );
|
BlockPos = Vector3I.Truncate( Min );
|
||||||
|
|
||||||
Quad? closestQuad = null;
|
Vector3I normal = Vector3I.Zero;
|
||||||
Vector3 closest = new Vector3( float.MaxValue, float.MaxValue, float.MaxValue );
|
Vector3 intersect = origin + dir * t0;
|
||||||
IEnumerable<Quad> faces = IntersectionUtils.GetFaces( Min, Max );
|
float dist = float.PositiveInfinity;
|
||||||
foreach( QuadIntersection result in FindIntersectingTriangles( origin, dir, faces ) ) {
|
TestAxis( intersect.X - Min.X, ref dist, -Vector3I.UnitX, ref normal );
|
||||||
Vector3 I = result.Intersection;
|
TestAxis( intersect.X - Max.X, ref dist, Vector3I.UnitX, ref normal );
|
||||||
if( ( origin - I ).LengthSquared < ( origin - closest ).LengthSquared ) {
|
TestAxis( intersect.Y - Min.Y, ref dist, -Vector3I.UnitY, ref normal );
|
||||||
closest = I;
|
TestAxis( intersect.Y - Max.Y, ref dist, Vector3I.UnitY, ref normal );
|
||||||
closestQuad = result.Quad;
|
TestAxis( intersect.Z - Min.Z, ref dist, -Vector3I.UnitZ, ref normal );
|
||||||
}
|
TestAxis( intersect.Z - Max.Z, ref dist, Vector3I.UnitZ, ref normal );
|
||||||
}
|
TranslatedPos = BlockPos + normal;
|
||||||
if( closestQuad != null ) {
|
|
||||||
TranslatedPos = Vector3I.Truncate( Min + closestQuad.Value.Normal );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void TestAxis( float dAxis, ref float dist, Vector3I nAxis, ref Vector3I normal ) {
|
||||||
static IEnumerable<QuadIntersection> FindIntersectingTriangles( Vector3 origin, Vector3 dir, IEnumerable<Quad> quads ) {
|
dAxis = Math.Abs( dAxis );
|
||||||
foreach( Quad quad in quads ) {
|
if( dAxis < dist ) {
|
||||||
Vector3 p0 = quad.Pos1; // assumed to be min point
|
dist = dAxis;
|
||||||
Vector3 p2 = quad.Pos3; // assumed to be max point
|
normal = nAxis;
|
||||||
Vector3 I;
|
|
||||||
|
|
||||||
Vector3 p1 = quad.Pos2; // triangle 1
|
|
||||||
if( IntersectionUtils.RayTriangleIntersect( origin, dir, p0, p1, p2, out I ) ) {
|
|
||||||
yield return new QuadIntersection( quad, I );
|
|
||||||
}
|
|
||||||
|
|
||||||
p1 = quad.Pos4; // triangle 2
|
|
||||||
if( IntersectionUtils.RayTriangleIntersect( origin, dir, p0, p1, p2, out I ) ) {
|
|
||||||
yield return new QuadIntersection( quad, I );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,6 +251,9 @@ namespace ClassicalSharp {
|
|||||||
public struct Vector3I {
|
public struct Vector3I {
|
||||||
|
|
||||||
public static Vector3I Zero = new Vector3I( 0, 0, 0 );
|
public static Vector3I Zero = new Vector3I( 0, 0, 0 );
|
||||||
|
public static Vector3I UnitX = new Vector3I( 1, 0, 0 );
|
||||||
|
public static Vector3I UnitY = new Vector3I( 0, 1, 0 );
|
||||||
|
public static Vector3I UnitZ = new Vector3I( 0, 0, 1 );
|
||||||
|
|
||||||
public int X, Y, Z;
|
public int X, Y, Z;
|
||||||
|
|
||||||
@ -287,6 +290,10 @@ namespace ClassicalSharp {
|
|||||||
return new Vector3I( left.X - right.X, left.Y - right.Y, left.Z - right.Z );
|
return new Vector3I( left.X - right.X, left.Y - right.Y, left.Z - right.Z );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Vector3I operator - ( Vector3I left ) {
|
||||||
|
return new Vector3I( -left.X, -left.Y, -left.Z );
|
||||||
|
}
|
||||||
|
|
||||||
public static explicit operator Vector3I( Vector3 value ) {
|
public static explicit operator Vector3I( Vector3 value ) {
|
||||||
return Truncate( value );
|
return Truncate( value );
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user