jensjeflensje / minecraft_imagery

Toolkit for taking pictures and videos in Minecraft
https://www.spigotmc.org/resources/imageryapi-take-pictures-in-minecraft.111347/
MIT License
18 stars 3 forks source link

transparent/ignored blocks can cause rays to go through solid blocks #9

Open kuraiskrap opened 1 month ago

kuraiskrap commented 1 month ago

I noticed it alot with grass blocks but i didn't realize the issue until later

my suspected cause .add(rayTraceVector.normalize()) normalized vector of 1 meter means that at angles the new raytrace starts 1 meter infront of the hitpoint but depending on where the block hit and at what angle, it can start raytracing past the next block it should hit

examples this one shows it pulling the blocks below in the cave with higher light levels image this one shows glass panes causing it to ignore the grass blocks and show sky above and passing through the attached block and hitting the side of the next one image this one shows the 0 light level being treated as full brightness in a night photo of grass (think due to the angle its hitting the side of the next block) image

not sure what the fix is, i noticed it with other blocks aswell i think that when its doing a raytrace from the hitpoint, it wont check for blocks within a certain starting distance causing it to passthrough the block behind it aswell

took the photos with your version to avoid issues with my fork

my fork now has this terrible jankfix if its hit grass already && the light level is 0 && block on hitface side is non passable i hardcoded it to be green, it honestly isnt terrible image

ConnorBP commented 2 weeks ago

I think there are functions out there that have been designed to generate step sizes for voxel raymarching of the correct length to avoid misses depending on ray angle and starting position. Might be worth replacing the static step size with this type of approach to fix this. https://youtu.be/gXSHtBZFxEI?t=146

ConnorBP commented 2 weeks ago

Something along these lines should work for step size calculation:

// get the shortest distance to the next block intersection and it's coordinates
public static double[] findFirstIntersection(Vector start, Vector direction) {
      double x = start.getX();
      double y = start.getY();
      double z = start.getZ();
      double dx = direction.getX();
      double dy = direction.getY();
      double dz = direction.getZ();

      // Calculate t values for each axis
      double tx = (dx != 0) ? ((dx > 0 ? Math.ceil(x) : Math.floor(x)) - x) / dx : Double.POSITIVE_INFINITY;
      double ty = (dy != 0) ? ((dy > 0 ? Math.ceil(y) : Math.floor(y)) - y) / dy : Double.POSITIVE_INFINITY;
      double tz = (dz != 0) ? ((dz > 0 ? Math.ceil(z) : Math.floor(z)) - z) / dz : Double.POSITIVE_INFINITY;

      // Handle cases where position is already at the boundary by moving to the next integer
      if (tx == 0) tx = 1.0 / Math.abs(dx);
      if (ty == 0) ty = 1.0 / Math.abs(dy);
      if (tz == 0) tz = 1.0 / Math.abs(dz);

      // Find the minimum positive t value
      double t = Math.min(tx, Math.min(ty, tz));

      // Calculate the intersection point
      double intersectX = x + t * dx;
      double intersectY = y + t * dy;
      double intersectZ = z + t * dz;
     // return the x y and z of intersection with the step distance as the 4rth component
      return new double[]{intersectX, intersectY, intersectZ, t};
}