mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 18:15:28 -04:00
Do more accurate model picking with rotated AABBs, make sure to only return closest player in model picking.
This commit is contained in:
parent
e23b5aeda5
commit
43a7e35d64
@ -42,23 +42,6 @@ namespace ClassicalSharp {
|
||||
}
|
||||
}
|
||||
|
||||
public virtual BoundingBox PickingBounds {
|
||||
get {
|
||||
BoundingBox bb = Model.PickingBounds;
|
||||
float angle = YawRadians;
|
||||
// TODO: This would be a lot simpler and more accurate if we just did ray-oobb intersection.
|
||||
Vector3 x1z1 = Utils.RotateY( bb.Min.X, 0, bb.Min.Z, angle );
|
||||
Vector3 x1z2 = Utils.RotateY( bb.Min.X, 0, bb.Max.Z, angle );
|
||||
Vector3 x2z1 = Utils.RotateY( bb.Max.X, 0, bb.Min.Z, angle );
|
||||
Vector3 x2z2 = Utils.RotateY( bb.Max.X, 0, bb.Max.Z, angle );
|
||||
float minX = Math.Min( x1z1.X, Math.Min( x1z2.X, Math.Min( x2z2.X, x2z1.X ) ) );
|
||||
float maxX = Math.Max( x1z1.X, Math.Max( x1z2.X, Math.Max( x2z2.X, x2z1.X ) ) );
|
||||
float minZ = Math.Min( x1z1.Z, Math.Min( x1z2.Z, Math.Min( x2z2.Z, x2z1.Z ) ) );
|
||||
float maxZ = Math.Max( x1z1.Z, Math.Max( x1z2.Z, Math.Max( x2z2.Z, x2z1.Z ) ) );
|
||||
return new BoundingBox( minX, bb.Min.Y, minZ, maxX, bb.Max.Y, maxZ ).Offset( Position );
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void Despawn();
|
||||
|
||||
public abstract void Render( double deltaTime, float t );
|
||||
|
@ -33,17 +33,18 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
public byte GetClosetPlayer( Vector3 eyePos, Vector3 dir ) {
|
||||
float dist = float.PositiveInfinity;
|
||||
float closestDist = float.PositiveInfinity;
|
||||
byte targetId = 255;
|
||||
|
||||
for( int i = 0; i < Players.Length - 1; i++ ) { // -1 because we don't want to pick against local player
|
||||
Player p = Players[i];
|
||||
if( p == null ) continue;
|
||||
BoundingBox bounds = p.PickingBounds;
|
||||
float t0, t1;
|
||||
if( IntersectionUtils.RayIntersectsBox( eyePos, dir, bounds.Min, bounds.Max, out t0, out t1 ) ) {
|
||||
dist = t0;
|
||||
targetId = (byte)i;
|
||||
if( Intersection.RayIntersectsRotatedBox( eyePos, dir, p, out t0, out t1 ) ) {
|
||||
if( t0 < closestDist ) {
|
||||
closestDist = t0;
|
||||
targetId = (byte)i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return targetId;
|
||||
|
@ -4,7 +4,21 @@ using OpenTK;
|
||||
|
||||
namespace ClassicalSharp {
|
||||
|
||||
public static class IntersectionUtils {
|
||||
public static class Intersection {
|
||||
|
||||
internal static bool RayIntersectsRotatedBox( Vector3 origin, Vector3 dir, Player target, out float tMin, out float tMax ) {
|
||||
// This is the rotated AABB of the model
|
||||
// *
|
||||
// / \ we then perform a counter *---* and we can then do
|
||||
// ====>* x * rotation to the rotated AABB | x | a standard AABB test
|
||||
// \ / and ray origin and direction *---* with the rotated ray
|
||||
// * /
|
||||
// /
|
||||
Vector3 rotatedOrigin = target.Position + Utils.RotateY( origin - target.Position, -target.YawRadians );
|
||||
Vector3 rotatedDir = Utils.RotateY( dir, -target.YawRadians );
|
||||
BoundingBox bb = target.Model.PickingBounds.Offset( target.Position );
|
||||
return RayIntersectsBox( rotatedOrigin, rotatedDir, bb.Min, bb.Max, out tMin, out tMax );
|
||||
}
|
||||
|
||||
//http://www.cs.utah.edu/~awilliam/box/box.pdf
|
||||
public static bool RayIntersectsBox( Vector3 origin, Vector3 dir, Vector3 min, Vector3 max,
|
||||
|
@ -90,7 +90,7 @@ namespace ClassicalSharp {
|
||||
// This cell falls on the path of the ray. Now perform an additional bounding box test,
|
||||
// since some blocks do not occupy a whole cell.
|
||||
float t0, t1;
|
||||
if( IntersectionUtils.RayIntersectsBox( origin, dir, min, max, out t0, out t1 ) ) {
|
||||
if( Intersection.RayIntersectsBox( origin, dir, min, max, out t0, out t1 ) ) {
|
||||
pickedPos.UpdateBlockPos( min, max, origin, dir, t0, t1 );
|
||||
return;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
public override void GetPickedBlock( PickedPos pos ) {
|
||||
Vector3 dir = Utils.GetDirectionVector( player.YawRadians, player.PitchRadians + Math.PI );
|
||||
Vector3 dir = Utils.GetDirVector( player.YawRadians, player.PitchRadians );
|
||||
Vector3 eyePos = player.EyePosition;
|
||||
float reach = Window.LocalPlayer.ReachDistance;
|
||||
Picking.GetPickedBlockPos( Window, eyePos, dir, reach, pos );
|
||||
@ -108,7 +108,7 @@ namespace ClassicalSharp {
|
||||
|
||||
public override Matrix4 GetView() {
|
||||
Vector3 eyePos = player.EyePosition;
|
||||
Vector3 cameraPos = eyePos - Utils.GetDirectionVector( player.YawRadians, player.PitchRadians + Math.PI ) * distance;
|
||||
Vector3 cameraPos = eyePos - Utils.GetDirVector( player.YawRadians, player.PitchRadians ) * distance;
|
||||
return Matrix4.LookAt( cameraPos, eyePos, Vector3.UnitY );
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ namespace ClassicalSharp {
|
||||
|
||||
public override Matrix4 GetView() {
|
||||
Vector3 eyePos = player.EyePosition;
|
||||
Vector3 cameraDir = Utils.GetDirectionVector( player.YawRadians, player.PitchRadians + Math.PI );
|
||||
Vector3 cameraDir = Utils.GetDirVector( player.YawRadians, player.PitchRadians );
|
||||
return Matrix4.LookAt( eyePos, eyePos + cameraDir, Vector3.UnitY );
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,12 @@ namespace ClassicalSharp {
|
||||
return packed * 360.0 / 256.0;
|
||||
}
|
||||
|
||||
public static Vector3 RotateY( Vector3 v, float angle ) {
|
||||
float cosA = (float)Math.Cos( angle );
|
||||
float sinA = (float)Math.Sin( angle );
|
||||
return new Vector3( cosA * v.X - sinA * v.Z, v.Y, sinA * v.X + cosA * v.Z );
|
||||
}
|
||||
|
||||
public static Vector3 RotateY( float x, float y, float z, float angle ) {
|
||||
float cosA = (float)Math.Cos( angle );
|
||||
float sinA = (float)Math.Sin( angle );
|
||||
@ -138,10 +144,10 @@ namespace ClassicalSharp {
|
||||
return dx * dx + dy * dy + dz * dz;
|
||||
}
|
||||
|
||||
public static Vector3 GetDirectionVector( double yawRad, double pitchRad ) {
|
||||
double x = Math.Cos( pitchRad ) * -Math.Sin( yawRad );
|
||||
double y = Math.Sin( pitchRad );
|
||||
double z = Math.Cos( pitchRad ) * Math.Cos( yawRad );
|
||||
public static Vector3 GetDirVector( double yawRad, double pitchRad ) {
|
||||
double x = -Math.Cos( pitchRad ) * -Math.Sin( yawRad );
|
||||
double y = -Math.Sin( pitchRad );
|
||||
double z = -Math.Cos( pitchRad ) * Math.Cos( yawRad );
|
||||
return new Vector3( (float)x, (float)y, (float)z );
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user