From 907b3ffc4ae2af0076f61e85096e622e97db4621 Mon Sep 17 00:00:00 2001 From: Octal Date: Sun, 15 Oct 2023 22:30:25 -0500 Subject: [PATCH] Rearrange some stuff in Raycast.cs --- Common/Util/PositionExtensions.cs | 6 +- Common/World/Raycast.cs | 92 +++++++++++++------------------ 2 files changed, 41 insertions(+), 57 deletions(-) diff --git a/Common/Util/PositionExtensions.cs b/Common/Util/PositionExtensions.cs index 9557f26..0c95338 100644 --- a/Common/Util/PositionExtensions.cs +++ b/Common/Util/PositionExtensions.cs @@ -20,10 +20,8 @@ public static ivec3 WorldToChunkPosition(this dvec3 worldPosition) { public static ivec3 BlockToChunkPosition(this ivec3 worldPosition) => WorldToChunkPosition(worldPosition); - public static ivec3 WorldToBlockPosition(this dvec3 worldPosition) { - var floored = dvec3.Floor(worldPosition); - return new((int)floored.x, (int)floored.y, (int)floored.z); - } + public static ivec3 WorldToBlockPosition(this dvec3 worldPosition) + => (ivec3)dvec3.Floor(worldPosition); public static dvec3 ChunkToWorldPosition(this ivec3 chunkPosition) => (dvec3)chunkPosition * ChunkSize; diff --git a/Common/World/Raycast.cs b/Common/World/Raycast.cs index 564f729..411a932 100644 --- a/Common/World/Raycast.cs +++ b/Common/World/Raycast.cs @@ -1,8 +1,5 @@ // Based off of this paper: http://www.cse.yorku.ca/~amana/research/grid.pdf -using System.Reflection.Metadata.Ecma335; -using System.Security.Cryptography; -using FastNoiseOO.Generators; using GlmSharp; using Voxel.Common.Util; using Voxel.Common.World.Views; @@ -10,21 +7,7 @@ namespace Voxel.Common.World; public static class Raycast { - private static double Mod1(double a) - => (a % 1 + 1) % 1; - - private static double GetTMax(double start, double tDelta, double step) - => FixNaN(tDelta * (step > 0 ? 1 - Mod1(start) : Mod1(start))); - - private static double FixNaN(double d) - => double.IsNaN(d) ? 0 : d; - - public static HitResult? Cast(this BlockView world, dvec3 start, dvec3 end, ivec3 looking) { - var startPos = start.WorldToBlockPosition(); - - if (world.GetBlock(startPos).IsSolidBlock) - return new(startPos, start); - + public static HitResult? Cast(this BlockView world, dvec3 start, dvec3 end, ivec3 looking) { var delta = end - start; double @@ -54,33 +37,13 @@ private static double FixNaN(double d) var yAxis = stepY > 0 ? ivec3.UnitY : -ivec3.UnitY; var zAxis = stepZ > 0 ? ivec3.UnitZ : -ivec3.UnitZ; - var endPos = (ivec3)end; + var endPos = end.WorldToBlockPosition(); + var axis = looking; while (true) { - ivec3 axis; - - switch (tMaxX < tMaxY) { - case true when tMaxX < tMaxZ: - axis = xAxis; - x += stepX; - tMaxX += tDeltaX; - break; - case false when tMaxY < tMaxZ: - axis = yAxis; - y += stepY; - tMaxY += tDeltaY; - break; - default: - axis = zAxis; - z += stepZ; - tMaxZ += tDeltaZ; - break; - } - var blockPos = new dvec3(x, y, z).WorldToBlockPosition(); if (world.GetBlock(blockPos).IsSolidBlock) { - // TODO: Account for non-cubic colliders at some point // Gets the one integer intersection coordinate // axis * blockPos isolates one coordinate from blockPos @@ -93,36 +56,59 @@ private static double FixNaN(double d) double time = (start.x - worldPos.x) / direction.x; worldPos.y = (int)(direction.y * time); worldPos.z = (int)(direction.z * time); + return new(blockPos, worldPos, axis); } - // intersect with a xz plane - else if (axis.y != 0) { + // intersect with an xz plane + if (axis.y != 0) { double time = (start.y - worldPos.y) / direction.y; worldPos.x = (int)(direction.x * time); worldPos.z = (int)(direction.z * time); + return new(blockPos, worldPos, axis); } // intersect with a xy plane - else if (axis.z != 0) { + if (axis.z != 0) { double time = (start.z - worldPos.z) / direction.z; worldPos.x = (int)(direction.x * time); worldPos.y = (int)(direction.y * time); + return new(blockPos, worldPos, axis); } - else continue; - - return new(blockPos, worldPos); } if (blockPos == endPos) return null; + + switch (tMaxX < tMaxY) { + case true when tMaxX < tMaxZ: + axis = xAxis; + x += stepX; + tMaxX += tDeltaX; + break; + case false when tMaxY < tMaxZ: + axis = yAxis; + y += stepY; + tMaxY += tDeltaY; + break; + default: + axis = zAxis; + z += stepZ; + tMaxZ += tDeltaZ; + break; + } } } + + private static double Mod1(double a) + => (a % 1 + 1) % 1; - public record struct HitResult { - public readonly ivec3 BlockPos; - public readonly dvec3 WorldPos; + private static double GetTMax(double start, double tDelta, double step) + => FixNaN(tDelta * (step > 0 ? 1 - Mod1(start) : Mod1(start))); - public HitResult(ivec3 block, dvec3 world) { - BlockPos = block; - WorldPos = world; - } + private static double FixNaN(double d) + => double.IsNaN(d) ? 0 : d; + + public record struct HitResult(ivec3 BlockPos, dvec3 WorldPos, ivec3 Axis) { + public readonly ivec3 BlockPos = BlockPos; + public readonly dvec3 WorldPos = WorldPos; + public readonly ivec3 Axis = Axis; } }