<p>Have you confirmed that objects that clip a chunk border are stored in both chunks?</p>

<p>Have you confirmed that octrA[map.x/2][map.y/2][map.z/2] can't point to anything weird?</p>

<p>In fact, what even is octrA? I assume that it's the array storing the chunks but I can't know for sure because I couldn't find it anywhere else in your code.</p>

<p>Other than that I'm having a bit of a hard time interpreting the problem and your code. Could you add some pictures and comments to your code?</p>

CC BY-SA 4.0
2019-12-17T13:26:14.657Z
2019-12-17T13:26:14.657Z
AnnoyinC
<p>I am attempting to implement chunks/octrees to speed up my render times. However, sometimes the walls show horizontal or vertical lines (rays hitting the inside of voxels?) or some blocks disappear altogether, although sometimes everything renders fine.</p>

<p>Edit: Yes, the chunks are stored fine. OctrA stands for OctreeA,  which is the chunk.
Edit: I reversed the ray for two steps after hitting a chunk. Although the glitches have gotten better, there is still the same problem.</p>

<pre><code>
      float cameraX = x/(float)HALFRESX -1;// -1 to 1
      struct Point3D rayd;
      rayd.x = dir.x + plane.x * cameraX;
      rayd.y = dir.y + plane.y * cameraX;

      struct Point3D delta;
      delta.x = fabsf(1/rayd.x);
      delta.y = fabsf(1/rayd.y);

      int zy = -HALFRESY;

      struct pos map;
      map.x = (char)pos.x;
      map.y = (char)pos.y;

      float sdistX;
      float sdistY;
      struct pos s;
      struct pos step;
      struct Point3D sdist;
      if(rayd.x &lt; 0) {
        step.x = -1;
        s.x = 1;
        sdistX = (pos.x - map.x) * delta.x; 
      }
      else {
        step.x = 1;
        s.x = 0;
        sdistX = (map.x + 1 - pos.x) * delta.x; 
      }
      if(rayd.y &lt; 0) {
        step.y = -1;
        s.y = 1;
        sdistY = (pos.y - map.y) * delta.y; 
      }
      else {
        step.y = 1;
        s.y = 0;
        sdistY = (map.y + 1 - pos.y) * delta.y; 
      }

      for(int y = 0; y &lt; RESY; y += 1) { 

        zy++;
        float cameraY = y/(float)HALFRESY - 1;
        rayd.z = dir.z + plane.z * cameraY;
        delta.z = fabsf(1/rayd.z);

        map.x = (char)pos.x;
        map.y = (char)pos.y;
        map.z = (char)pos.z;
        sdist.x = sdistX;
        sdist.y = sdistY; 

        if(rayd.z &lt; 0) {
          step.z = -1;
          s.z = 1;
          sdist.z = (pos.z - map.z) * delta.z; 
        }
        else {
          step.z = 1;
          s.z = 0;
          sdist.z = (map.z + 1 - pos.z) * delta.z; 
        }
#ifdef USE_OCTREE

        while( !octrA[map.x/2][map.y/2][map.z/2]) {
          if(sdist.y &lt; sdist.x ) {
            if(sdist.y &lt; sdist.z) {
              sdist.y += delta.y*2;
              map.y += step.y*2;
            }
            else {
              sdist.z += delta.z*2;
              map.z += step.z*2;
            }
          }
          else {
            if(sdist.x &lt; sdist.z) {
              sdist.x += delta.x*2;
              map.x += step.x*2;
            }
            else {
              sdist.z += delta.z*2;
              map.z += step.z*2; 
            }
          }
        }
        if(octr) {
          if(sdist.y &gt; sdist.x ) {
            if(sdist.y &gt; sdist.z) {
              sdist.y -= delta.y*2;
              map.y -= step.y*2;
            }
            else {
              sdist.z -= delta.z*2;
              map.z -= step.z*2;
            }
          }
          else {
            if(sdist.x &gt; sdist.z) {
              sdist.x -= delta.x*2;
              map.x -= step.x*2;
            }
            else {
              sdist.z -= delta.z*2;
              map.z -= step.z*2; 
            }
          }
        }

#endif
        char side; //either 0 (NS), or 1 (EW), or 2(UD)
        while( !MAP[map.x][map.y][map.z]) {
          if(sdist.y &lt; sdist.x ) {
            if(sdist.y &lt; sdist.z) {
              sdist.y += delta.y;
              map.y += step.y;
              side = 1; // y
            }
            else {
              sdist.z += delta.z;
              map.z += step.z;
              side = 2; 
            }
          }
          else {
            if(sdist.x &lt; sdist.z) {
              sdist.x += delta.x;
              map.x += step.x;
              side = 0; 
            }
            else {
              sdist.z += delta.z;
              map.z += step.z; 
              side = 2; 
            }
          }
        }

</code></pre>

CC BY-SA 4.0
2019-12-18T05:47:48.560Z
rayd.x = dir.x + plane.x * cameraX;
      rayd.y = dir.y + plane.y * cameraX;  -- Shouldn't that second rayd.y assignment be taking a cameraY variable instead ?
PaulHK
CC BY-SA 4.0
2019-12-18T09:24:22.620Z
CameraX is -1 to 1 and corresponds with the X axis on screen, so no
Russell356
CC BY-SA 4.0
2021-01-12T08:45:03.910Z
I apologise for not reading your code, but by your description of the errors I'd hazard a guess that you need to make your octree testing maths *conservative* i.e. either use 1) rounding modes that round down or round up appropriately, or 2) add/subtract some "epsilson" safety margin on to the calculations when testing the bounds.   Remember FP maths is rarely exact and unlucky rounding could mean an object very near to a boundary of an octree might be "missed" by the octree test yet would return a hit if tested directly.
Simon F
CC BY-SA 4.0
2021-09-10T10:42:47.317Z
So this is more of a debugging chore then a how to implement it question. I don't see any logic sanity checking the values of x,y,z in the tree lookup code. A nice simple first step to finding the issue is to sanity check map.x/y/z in the while loop. Something like assert(map.x < mapx_max_val) and the same thing for y/z.
pmw1234
<raytracing><3d>
How can I raycast with chunks?
Russell356
# How can I raycast with chunks?

(Asked by: username_0 on 2019-12-17)

I am attempting to implement chunks/octrees to speed up my render times. However, sometimes the walls show horizontal or vertical lines (rays hitting the inside of voxels?) or some blocks disappear altogether, although sometimes everything renders fine.

Edit: Yes, the chunks are stored fine. OctrA stands for OctreeA, which is the chunk.
Edit: I reversed the ray for two steps after hitting a chunk. Although the glitches have gotten better, there is still the same problem.

```

      float cameraX = x/(float)HALFRESX -1;// -1 to 1
      struct Point3D rayd;
      rayd.x = dir.x + plane.x * cameraX;
      rayd.y = dir.y + plane.y * cameraX;

      struct Point3D delta;
      delta.x = fabsf(1/rayd.x);
      delta.y = fabsf(1/rayd.y);

      int zy = -HALFRESY;

      struct pos map;
      map.x = (char)pos.x;
      map.y = (char)pos.y;

      float sdistX;
      float sdistY;
      struct pos s;
      struct pos step;
      struct Point3D sdist;
      if(rayd.x < 0) {
        step.x = -1;
        s.x = 1;
        sdistX = (pos.x - map.x) * delta.x; 
      }
      else {
        step.x = 1;
        s.x = 0;
        sdistX = (map.x + 1 - pos.x) * delta.x; 
      }
      if(rayd.y < 0) {
        step.y = -1;
        s.y = 1;
        sdistY = (pos.y - map.y) * delta.y; 
      }
      else {
        step.y = 1;
        s.y = 0;
        sdistY = (map.y + 1 - pos.y) * delta.y; 
      }

      for(int y = 0; y < RESY; y += 1) { 

        zy++;
        float cameraY = y/(float)HALFRESY - 1;
        rayd.z = dir.z + plane.z * cameraY;
        delta.z = fabsf(1/rayd.z);

        map.x = (char)pos.x;
        map.y = (char)pos.y;
        map.z = (char)pos.z;
        sdist.x = sdistX;
        sdist.y = sdistY; 

        if(rayd.z < 0) {
          step.z = -1;
          s.z = 1;
          sdist.z = (pos.z - map.z) * delta.z; 
        }
        else {
          step.z = 1;
          s.z = 0;
          sdist.z = (map.z + 1 - pos.z) * delta.z; 
        }
#ifdef USE_OCTREE

        while( !octrA[map.x/2][map.y/2][map.z/2]) {
          if(sdist.y < sdist.x ) {
            if(sdist.y < sdist.z) {
              sdist.y += delta.y*2;
              map.y += step.y*2;
            }
            else {
              sdist.z += delta.z*2;
              map.z += step.z*2;
            }
          }
          else {
            if(sdist.x < sdist.z) {
              sdist.x += delta.x*2;
              map.x += step.x*2;
            }
            else {
              sdist.z += delta.z*2;
              map.z += step.z*2; 
            }
          }
        }
        if(octr) {
          if(sdist.y > sdist.x ) {
            if(sdist.y > sdist.z) {
              sdist.y -= delta.y*2;
              map.y -= step.y*2;
            }
            else {
              sdist.z -= delta.z*2;
              map.z -= step.z*2;
            }
          }
          else {
            if(sdist.x > sdist.z) {
              sdist.x -= delta.x*2;
              map.x -= step.x*2;
            }
            else {
              sdist.z -= delta.z*2;
              map.z -= step.z*2; 
            }
          }
        }

#endif
        char side; //either 0 (NS), or 1 (EW), or 2(UD)
        while( !MAP[map.x][map.y][map.z]) {
          if(sdist.y < sdist.x ) {
            if(sdist.y < sdist.z) {
              sdist.y += delta.y;
              map.y += step.y;
              side = 1; // y
            }
            else {
              sdist.z += delta.z;
              map.z += step.z;
              side = 2; 
            }
          }
          else {
            if(sdist.x < sdist.z) {
              sdist.x += delta.x;
              map.x += step.x;
              side = 0; 
            }
            else {
              sdist.z += delta.z;
              map.z += step.z; 
              side = 2; 
            }
          }
        }

```

**Tags:** raytracing, 3d

> **Comments:**
> **username_1**: rayd.x = dir.x + plane.x * cameraX;       rayd.y = dir.y + plane.y * cameraX;  -- Shouldn't that second rayd.y assignment be taking a cameraY variable instead ?  
> **username_0**: CameraX is -1 to 1 and corresponds with the X axis on screen, so no  
> **username_2**: I apologise for not reading your code, but by your description of the errors I'd hazard a guess that you need to make your octree testing maths *conservative* i.e. either use 1) rounding modes that round down or round up appropriately, or 2) add/subtract some "epsilson" safety margin on to the calculations when testing the bounds.   Remember FP maths is rarely exact and unlucky rounding could mean an object very near to a boundary of an octree might be "missed" by the octree test yet would return a hit if tested directly.  
> **username_3**: So this is more of a debugging chore then a how to implement it question. I don't see any logic sanity checking the values of x,y,z in the tree lookup code. A nice simple first step to finding the issue is to sanity check map.x/y/z in the while loop. Something like assert(map.x < mapx_max_val) and the same thing for y/z.  

---

## 1 answers

### Answer by username_4 on 2019-12-17. Score: 0

Have you confirmed that objects that clip a chunk border are stored in both chunks?

Have you confirmed that octrA[map.x/2][map.y/2][map.z/2] can't point to anything weird?

In fact, what even is octrA? I assume that it's the array storing the chunks but I can't know for sure because I couldn't find it anywhere else in your code.

Other than that I'm having a bit of a hard time interpreting the problem and your code. Could you add some pictures and comments to your code?


---

