diff --git a/inc/excess.h b/inc/excess.h index 36d7c08..cfebe9e 100644 --- a/inc/excess.h +++ b/inc/excess.h @@ -169,234 +169,303 @@ int PTIB2(const char x, const char y, const char z) //************************************* // ray functions //*************************************/ -int ray(vec* hit_pos, vec pos) // look vector is still a global, not going to mess with that for now +int ray(vec* hit_pos, vec* hit_vec, const vec start_pos) // the look vector is a global { - vec dir = { - .x = look_dir.x >= 0 ? 1 : -1, - .y = look_dir.y >= 0 ? 1 : -1, - .z = look_dir.z >= 0 ? 1 : -1, - }; - - vec dir2 = { - .x = dir.x/2.f, - .y = dir.y/2.f, - .z = dir.z/2.f, - }; - - vec dist_per = { - .x = dir.x / look_dir.x, // inverse, but positive - .y = dir.y / look_dir.y, - .z = dir.z / look_dir.z, - }; - - vec dist_remaining = { - .x = (((dir.x + 1.f) / 2.f) - ((pos.x + 0.5f) - floorf(pos.x + 0.5f))) / look_dir.x, - .y = (((dir.y + 1.f) / 2.f) - ((pos.y + 0.5f) - floorf(pos.y + 0.5f))) / look_dir.y, - .z = (((dir.z + 1.f) / 2.f) - ((pos.z + 0.5f) - floorf(pos.z + 0.5f))) / look_dir.z, - }; - - - if (pos.x < -0.5f || pos.x > 127.5f || pos.y < -0.5f || pos.y > 127.5f || pos.z < -0.5f || pos.z > 127.5f) { // find how far it'd take to get into the world, if not in it in the first place - vec maxdist; - if (pos.x < -0.5f) { - maxdist.x = -((pos.x + 0.5f) / look_dir.x); - if (maxdist.x < 0.f) { - return -1; - } - } else if (pos.x > 127.5f) { - maxdist.x = -((pos.x - 127.5f) / look_dir.x); - if (maxdist.x < 0.f) { - return -1; - } - } else { - maxdist.x = 0.f; - } - - if (pos.y < -0.5f) { - maxdist.y = -((pos.y + 0.5f) / look_dir.y); - if (maxdist.y < 0.f) { - return -1; - } - } else if (pos.y > 127.7f) { - maxdist.y = -((pos.y - 127.5f) / look_dir.y); - if (maxdist.y < 0.f) { - return -1; - } - } else { - maxdist.y = 0.f; - } - - if (pos.z < -0.5f) { - maxdist.z = -((pos.z + 0.5f) / look_dir.z); - if (maxdist.x < 0.f) { - return -1; - } - } else if (pos.z > 127.7f) { - maxdist.z = -((pos.z - 127.5f) / look_dir.z); - if (maxdist.z < 0.f) { - return -1; - } - } else { - maxdist.z = 0.f; - } - - maxdist.w = maxdist.x; - if (maxdist.w < maxdist.y) { - maxdist.w = maxdist.y; - } - if (maxdist.w < maxdist.z) { - maxdist.w = maxdist.z; - } - - pos.x += maxdist.w * look_dir.x; - pos.y += maxdist.w * look_dir.y; - pos.z += maxdist.w * look_dir.z; - - dist_remaining = (vec){ - .x = (((dir.x + 1.f) * 0.5f) - ((pos.x + 0.5f) - floorf(pos.x + 0.5f))) / look_dir.x, - .y = (((dir.y + 1.f) * 0.5f) - ((pos.y + 0.5f) - floorf(pos.y + 0.5f))) / look_dir.y, - .z = (((dir.z + 1.f) * 0.5f) - ((pos.z + 0.5f) - floorf(pos.z + 0.5f))) / look_dir.z, - }; - - if (maxdist.w == maxdist.x) { - if (pos.y < -0.5f || pos.y > 127.5f || pos.z < -0.5f || pos.z > 127.5f) { // floating point inaccuracies are fun... hopefully this won't go wrong, if it does well... user can just move - return -1; - } - - dist_remaining.x = dist_per.x; - - int index = PTI(pos.x + dir2.x + 0.5f, pos.y + 0.5f, pos.z + 0.5f); - if (g.voxels[index]) { - *hit_pos = (vec){ - .x = 0.1f + pos.x - dir2.x, - .y = 0.1f + roundf(pos.y), - .z = 0.1f + roundf(pos.z) - }; - return index; - } - } else if (maxdist.w == maxdist.y) { - if (pos.x < -0.5f || pos.x > 127.5f || pos.z < -0.5f || pos.z > 127.5f) { - return -1; - } - - dist_remaining.y = dist_per.y; - - int index = PTI(pos.x + 0.5f, pos.y + dir2.y + 0.5f, pos.z + 0.5f); - if (g.voxels[index]) { - *hit_pos = (vec){ - .x = 0.1f + roundf(pos.x), - .y = 0.1f + pos.y - dir2.y, - .z = 0.1f + roundf(pos.z) - }; - return index; - } - } else { - if (pos.x < -0.5f || pos.x > 127.5f || pos.y < -0.5f || pos.y > 127.5f) { - return -1; - } - - dist_remaining.z = dist_per.z; - - int index = PTI(pos.x + 0.5f, pos.y + 0.5f, pos.z + dir2.z + 0.5f); - if (g.voxels[index]) { - *hit_pos = (vec){ - .x = 0.1f + roundf(pos.x), - .y = 0.1f + roundf(pos.y), - .z = 0.1f + pos.z - dir2.z - }; - return index; - } - } - } - - - while (1) { - if (dist_remaining.x < dist_remaining.y && dist_remaining.x < dist_remaining.z) { - pos.x += look_dir.x * dist_remaining.x; - pos.y += look_dir.y * dist_remaining.x; - pos.z += look_dir.z * dist_remaining.x; - - dist_remaining.y -= dist_remaining.x; - dist_remaining.z -= dist_remaining.x; - - dist_remaining.x = dist_per.x; - - if (pos.x + dir.x > 127.f || pos.x + dir.x < 0.f) { // max valid going +x: 126.5, min -x: 0.5; max +x: 127.5, min -x: -0.5 - return -1; - } - - int index = PTI(pos.x + dir2.x + 0.5f, pos.y + 0.5f, pos.z + 0.5f); - if (g.voxels[index]) { - *hit_pos = (vec){ - .x = 0.1f + pos.x - dir2.x, - .y = 0.1f + roundf(pos.y), - .z = 0.1f + roundf(pos.z), - }; - // printf("Hit: (%.02f, %.02f, %.02f)\n", hit_pos->x, hit_pos->y, hit_pos->z); - return index; - } - } else if (dist_remaining.y < dist_remaining.z) { - pos.x += look_dir.x * dist_remaining.y; - pos.y += look_dir.y * dist_remaining.y; - pos.z += look_dir.z * dist_remaining.y; - - dist_remaining.x -= dist_remaining.y; - dist_remaining.z -= dist_remaining.y; - - dist_remaining.y = dist_per.y; - - if (pos.y + dir.y > 127.7f || pos.y + dir.y < -0.7f) { - return -1; - } - - int index = PTI(pos.x + 0.5f, pos.y + dir2.y + 0.5f, pos.z + 0.5f); - if (g.voxels[index]) { - *hit_pos = (vec){ - .x = 0.1f + roundf(pos.x), - .y = 0.1f + pos.y - dir2.y, - .z = 0.1f + roundf(pos.z), - }; - // printf("Hit: (%.02f, %.02f, %.02f)\n", hit_pos->x, hit_pos->y, hit_pos->z); - return index; - } - } else { - pos.x += look_dir.x * dist_remaining.z; - pos.y += look_dir.y * dist_remaining.z; - pos.z += look_dir.z * dist_remaining.z; - - dist_remaining.x -= dist_remaining.z; - dist_remaining.y -= dist_remaining.z; - - dist_remaining.z = dist_per.z; - - if (pos.z + dir.z > 127.7f || pos.z + dir.z < -0.7f) { - return -1; - } - - int index = PTI(pos.x + 0.5f, pos.y + 0.5f, pos.z + dir2.z + 0.5f); - if (g.voxels[index]) { - *hit_pos = (vec){ - .x = 0.1f + roundf(pos.x), - .y = 0.1f + roundf(pos.y), - .z = 0.1f + pos.z - dir2.z, - }; - // printf("Hit: (%.02f, %.02f, %.02f)\n", hit_pos->x, hit_pos->y, hit_pos->z); - return index; - } - } - } + // might need exclude conditions for obviously bogus rays to avoid those 2048 steps + vec inc; + vMulS(&inc, look_dir, 0.015625f); // 0.0625f + int hit = -1; + vec rp = start_pos; + for(uint i = 0; i < 8192; i++) // 2048 + { + vAdd(&rp, rp, inc); + if(isInBounds(rp) == 0){continue;} // break; + vec rb; + rb.x = roundf(rp.x); + rb.y = roundf(rp.y); + rb.z = roundf(rp.z); + const uint vi = PTI(rb.x, rb.y, rb.z); + //printf("ray: %u: %f %f %f\n", vi, rb.x, rb.y, rb.z); + if(g.voxels[vi] != 0) + { + *hit_vec = (vec){rp.x-rb.x, rp.y-rb.y, rp.z-rb.z}; + *hit_pos = (vec){rb.x, rb.y, rb.z}; + hit = vi; + break; + } + if(hit > -1){break;} + } + return hit; } void traceViewPath(const uint face) { g.pb.w = -1.f; // pre-set as failed - lray = ray(&ghp, ipp); + vec rp; + lray = ray(&ghp, &rp, ipp); if(lray > -1 && face == 1) { - g.pb = ghp; - g.pb.w = 1.f; // success + vNorm(&rp); + vec diff = rp; + rp = ghp; + + vec fd = diff; + fd.x = fabsf(diff.x); + fd.y = fabsf(diff.y); + fd.z = fabsf(diff.z); + if (fd.x > fd.y && fd.x > fd.z){diff.y = 0.f, diff.z = 0.f;} + else if(fd.y > fd.x && fd.y > fd.z){diff.x = 0.f, diff.z = 0.f;} + else if(fd.z > fd.x && fd.z > fd.y){diff.x = 0.f, diff.y = 0.f;} + diff.x = roundf(diff.x); + diff.y = roundf(diff.y); + diff.z = roundf(diff.z); + + rp.x += diff.x; + rp.y += diff.y; + rp.z += diff.z; + + if(vSumAbs(diff) == 1.f) + { + g.pb = rp; + g.pb.w = 1.f; // success + } } } +// int ray(vec* hit_pos, vec pos) // look vector is still a global, not going to mess with that for now +// { +// vec dir = { +// .x = look_dir.x >= 0 ? 1 : -1, +// .y = look_dir.y >= 0 ? 1 : -1, +// .z = look_dir.z >= 0 ? 1 : -1, +// }; + +// vec dir2 = { +// .x = dir.x/2.f, +// .y = dir.y/2.f, +// .z = dir.z/2.f, +// }; + +// vec dist_per = { +// .x = dir.x / look_dir.x, // inverse, but positive +// .y = dir.y / look_dir.y, +// .z = dir.z / look_dir.z, +// }; + +// vec dist_remaining = { +// .x = (((dir.x + 1.f) / 2.f) - ((pos.x + 0.5f) - floorf(pos.x + 0.5f))) / look_dir.x, +// .y = (((dir.y + 1.f) / 2.f) - ((pos.y + 0.5f) - floorf(pos.y + 0.5f))) / look_dir.y, +// .z = (((dir.z + 1.f) / 2.f) - ((pos.z + 0.5f) - floorf(pos.z + 0.5f))) / look_dir.z, +// }; + + +// if (pos.x < -0.5f || pos.x > 127.5f || pos.y < -0.5f || pos.y > 127.5f || pos.z < -0.5f || pos.z > 127.5f) { // find how far it'd take to get into the world, if not in it in the first place +// vec maxdist; +// if (pos.x < -0.5f) { +// maxdist.x = -((pos.x + 0.5f) / look_dir.x); +// if (maxdist.x < 0.f) { +// return -1; +// } +// } else if (pos.x > 127.5f) { +// maxdist.x = -((pos.x - 127.5f) / look_dir.x); +// if (maxdist.x < 0.f) { +// return -1; +// } +// } else { +// maxdist.x = 0.f; +// } + +// if (pos.y < -0.5f) { +// maxdist.y = -((pos.y + 0.5f) / look_dir.y); +// if (maxdist.y < 0.f) { +// return -1; +// } +// } else if (pos.y > 127.7f) { +// maxdist.y = -((pos.y - 127.5f) / look_dir.y); +// if (maxdist.y < 0.f) { +// return -1; +// } +// } else { +// maxdist.y = 0.f; +// } + +// if (pos.z < -0.5f) { +// maxdist.z = -((pos.z + 0.5f) / look_dir.z); +// if (maxdist.x < 0.f) { +// return -1; +// } +// } else if (pos.z > 127.7f) { +// maxdist.z = -((pos.z - 127.5f) / look_dir.z); +// if (maxdist.z < 0.f) { +// return -1; +// } +// } else { +// maxdist.z = 0.f; +// } + +// maxdist.w = maxdist.x; +// if (maxdist.w < maxdist.y) { +// maxdist.w = maxdist.y; +// } +// if (maxdist.w < maxdist.z) { +// maxdist.w = maxdist.z; +// } + +// pos.x += maxdist.w * look_dir.x; +// pos.y += maxdist.w * look_dir.y; +// pos.z += maxdist.w * look_dir.z; + +// dist_remaining = (vec){ +// .x = (((dir.x + 1.f) * 0.5f) - ((pos.x + 0.5f) - floorf(pos.x + 0.5f))) / look_dir.x, +// .y = (((dir.y + 1.f) * 0.5f) - ((pos.y + 0.5f) - floorf(pos.y + 0.5f))) / look_dir.y, +// .z = (((dir.z + 1.f) * 0.5f) - ((pos.z + 0.5f) - floorf(pos.z + 0.5f))) / look_dir.z, +// }; + +// if (maxdist.w == maxdist.x) { +// if (pos.y < -0.5f || pos.y > 127.5f || pos.z < -0.5f || pos.z > 127.5f) { // floating point inaccuracies are fun... hopefully this won't go wrong, if it does well... user can just move +// return -1; +// } + +// dist_remaining.x = dist_per.x; + +// ghp = pos; +// int index = PTI(pos.x + dir2.x + 0.5f, pos.y + 0.5f, pos.z + 0.5f); +// if (g.voxels[index]) { +// *hit_pos = (vec){ +// .x = 0.1f + pos.x - dir2.x, +// .y = 0.1f + roundf(pos.y), +// .z = 0.1f + roundf(pos.z) +// }; +// return index; +// } +// } else if (maxdist.w == maxdist.y) { +// if (pos.x < -0.5f || pos.x > 127.5f || pos.z < -0.5f || pos.z > 127.5f) { +// return -1; +// } + +// dist_remaining.y = dist_per.y; + +// ghp = pos; +// int index = PTI(pos.x + 0.5f, pos.y + dir2.y + 0.5f, pos.z + 0.5f); +// if (g.voxels[index]) { +// *hit_pos = (vec){ +// .x = 0.1f + roundf(pos.x), +// .y = 0.1f + pos.y - dir2.y, +// .z = 0.1f + roundf(pos.z) +// }; +// return index; +// } +// } else { +// if (pos.x < -0.5f || pos.x > 127.5f || pos.y < -0.5f || pos.y > 127.5f) { +// return -1; +// } + +// dist_remaining.z = dist_per.z; + +// ghp = pos; +// int index = PTI(pos.x + 0.5f, pos.y + 0.5f, pos.z + dir2.z + 0.5f); +// if (g.voxels[index]) { +// *hit_pos = (vec){ +// .x = 0.1f + roundf(pos.x), +// .y = 0.1f + roundf(pos.y), +// .z = 0.1f + pos.z - dir2.z +// }; +// return index; +// } +// } +// } + + +// while (1) { +// if (dist_remaining.x < dist_remaining.y && dist_remaining.x < dist_remaining.z) { +// pos.x += look_dir.x * dist_remaining.x; +// pos.y += look_dir.y * dist_remaining.x; +// pos.z += look_dir.z * dist_remaining.x; + +// dist_remaining.y -= dist_remaining.x; +// dist_remaining.z -= dist_remaining.x; + +// dist_remaining.x = dist_per.x; + +// if (pos.x + dir.x > 127.f || pos.x + dir.x < 0.f) { // max valid going +x: 126.5, min -x: 0.5; max +x: 127.5, min -x: -0.5 +// return -1; +// } + +// ghp = pos; +// int index = PTI(pos.x + dir2.x, pos.y, pos.z); +// if (g.voxels[index]) { +// *hit_pos = (vec){ +// .x = 0.1f + pos.x - dir2.x, +// .y = 0.1f + roundf(pos.y), +// .z = 0.1f + roundf(pos.z), +// }; +// // printf("Hit: (%.02f, %.02f, %.02f)\n", hit_pos->x, hit_pos->y, hit_pos->z); +// return index; +// } +// } else if (dist_remaining.y < dist_remaining.z) { +// pos.x += look_dir.x * dist_remaining.y; +// pos.y += look_dir.y * dist_remaining.y; +// pos.z += look_dir.z * dist_remaining.y; + +// dist_remaining.x -= dist_remaining.y; +// dist_remaining.z -= dist_remaining.y; + +// dist_remaining.y = dist_per.y; + +// if (pos.y + dir.y > 127.7f || pos.y + dir.y < -0.7f) { +// return -1; +// } + +// ghp = pos; +// int index = PTI(pos.x + 0.5f, pos.y + dir2.y + 0.5f, pos.z + 0.5f); +// if (g.voxels[index]) { +// *hit_pos = (vec){ +// .x = 0.1f + roundf(pos.x), +// .y = 0.1f + pos.y - dir2.y, +// .z = 0.1f + roundf(pos.z), +// }; +// // printf("Hit: (%.02f, %.02f, %.02f)\n", hit_pos->x, hit_pos->y, hit_pos->z); +// return index; +// } +// } else { +// pos.x += look_dir.x * dist_remaining.z; +// pos.y += look_dir.y * dist_remaining.z; +// pos.z += look_dir.z * dist_remaining.z; + +// dist_remaining.x -= dist_remaining.z; +// dist_remaining.y -= dist_remaining.z; + +// dist_remaining.z = dist_per.z; + +// if (pos.z + dir.z > 127.7f || pos.z + dir.z < -0.7f) { +// return -1; +// } + +// ghp = pos; +// int index = PTI(pos.x + 0.5f, pos.y + 0.5f, pos.z + dir2.z + 0.5f); +// if (g.voxels[index]) { +// *hit_pos = (vec){ +// .x = 0.1f + roundf(pos.x), +// .y = 0.1f + roundf(pos.y), +// .z = 0.1f + pos.z - dir2.z, +// }; +// // printf("Hit: (%.02f, %.02f, %.02f)\n", hit_pos->x, hit_pos->y, hit_pos->z); +// return index; +// } +// } +// } +// } +// void traceViewPath(const uint face) +// { +// g.pb.w = -1.f; // pre-set as failed +// vec t; +// lray = ray(&t, ipp); +// if(lray > -1 && face == 1) +// { +// g.pb = t; +// g.pb.w = 1.f; // success +// } +// } + //************************************* // utility functions //*************************************