You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
4.0 KiB
150 lines
4.0 KiB
#include <map/ArrayMap.h>
|
|
|
|
|
|
|
|
ArrayMap::ArrayMap(sf::Vector3i dimensions) {
|
|
|
|
this->dimensions = dimensions;
|
|
|
|
voxel_data = new char[dimensions.x * dimensions.y * dimensions.z];
|
|
for (int i = 0; i < dimensions.x * dimensions.y * dimensions.z; i++) {
|
|
voxel_data[i] = 0;
|
|
//voxel_data[i] = 1;
|
|
}
|
|
|
|
setVoxel(sf::Vector3i(1, 1, 5), 1);
|
|
|
|
for (int x = 0; x < dimensions.x; x++) {
|
|
for (int y = 0; y < dimensions.y; y++) {
|
|
setVoxel(sf::Vector3i(x, y, 0), 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
ArrayMap::~ArrayMap() {
|
|
delete[] voxel_data;
|
|
}
|
|
|
|
char ArrayMap::getVoxel(sf::Vector3i position) {
|
|
return voxel_data[position.x + dimensions.x * (position.y + dimensions.z * position.z)];
|
|
}
|
|
|
|
|
|
void ArrayMap::setVoxel(sf::Vector3i position, char value) {
|
|
voxel_data[position.x + dimensions.x * (position.y + dimensions.z * position.z)] = value;
|
|
}
|
|
|
|
sf::Vector3i ArrayMap::getDimensions() {
|
|
return dimensions;
|
|
}
|
|
|
|
char* ArrayMap::getDataPtr() {
|
|
return voxel_data;
|
|
}
|
|
|
|
std::vector<std::tuple<sf::Vector3i, char>> ArrayMap::CastRayCharArray(
|
|
char* map,
|
|
sf::Vector3i* map_dim,
|
|
sf::Vector2f* cam_dir,
|
|
sf::Vector3f* cam_pos
|
|
) {
|
|
// Setup the voxel coords from the camera origin
|
|
sf::Vector3i voxel(*cam_pos);
|
|
|
|
std::vector<std::tuple<sf::Vector3i, char>> travel_path;
|
|
|
|
sf::Vector3f ray_dir(1, 0, 0);
|
|
|
|
// Pitch
|
|
ray_dir = sf::Vector3f(
|
|
ray_dir.z * sin((*cam_dir).x) + ray_dir.x * cos((*cam_dir).x),
|
|
ray_dir.y,
|
|
ray_dir.z * cos((*cam_dir).x) - ray_dir.x * sin((*cam_dir).x)
|
|
);
|
|
|
|
// Yaw
|
|
ray_dir = sf::Vector3f(
|
|
ray_dir.x * cos((*cam_dir).y) - ray_dir.y * sin((*cam_dir).y),
|
|
ray_dir.x * sin((*cam_dir).y) + ray_dir.y * cos((*cam_dir).y),
|
|
ray_dir.z
|
|
);
|
|
|
|
// correct for the base ray pointing to (1, 0, 0) as (0, 0). Should equal (1.57, 0)
|
|
ray_dir = sf::Vector3f(
|
|
static_cast<float>(ray_dir.z * sin(-1.57) + ray_dir.x * cos(-1.57)),
|
|
static_cast<float>(ray_dir.y),
|
|
static_cast<float>(ray_dir.z * cos(-1.57) - ray_dir.x * sin(-1.57))
|
|
);
|
|
|
|
|
|
// Setup the voxel step based on what direction the ray is pointing
|
|
sf::Vector3i voxel_step(1, 1, 1);
|
|
|
|
voxel_step.x *= (ray_dir.x > 0) - (ray_dir.x < 0);
|
|
voxel_step.y *= (ray_dir.y > 0) - (ray_dir.y < 0);
|
|
voxel_step.z *= (ray_dir.z > 0) - (ray_dir.z < 0);
|
|
|
|
|
|
// Delta T is the units a ray must travel along an axis in order to
|
|
// traverse an integer split
|
|
sf::Vector3f delta_t(
|
|
fabs(1.0f / ray_dir.x),
|
|
fabs(1.0f / ray_dir.y),
|
|
fabs(1.0f / ray_dir.z)
|
|
);
|
|
|
|
// offset is how far we are into a voxel, enables sub voxel movement
|
|
// Intersection T is the collection of the next intersection points
|
|
// for all 3 axis XYZ.
|
|
sf::Vector3f intersection_t(
|
|
delta_t.x * (cam_pos->x - floor(cam_pos->x)) * voxel_step.x,
|
|
delta_t.y * (cam_pos->y - floor(cam_pos->y)) * voxel_step.y,
|
|
delta_t.z * (cam_pos->z - floor(cam_pos->z)) * voxel_step.z
|
|
);
|
|
|
|
// for negative values, wrap around the delta_t
|
|
intersection_t.x -= delta_t.x * (std::min(intersection_t.x, 0.0f));
|
|
intersection_t.y -= delta_t.y * (std::min(intersection_t.y, 0.0f));
|
|
intersection_t.z -= delta_t.z * (std::min(intersection_t.z, 0.0f));
|
|
|
|
|
|
int dist = 0;
|
|
sf::Vector3i face_mask(0, 0, 0);
|
|
int voxel_data = 0;
|
|
|
|
// Andrew Woo's raycasting algo
|
|
do {
|
|
|
|
face_mask.x = intersection_t.x <= std::min(intersection_t.y, intersection_t.z);
|
|
face_mask.y = intersection_t.y <= std::min(intersection_t.z, intersection_t.x);
|
|
face_mask.z = intersection_t.z <= std::min(intersection_t.x, intersection_t.y);
|
|
|
|
intersection_t.x += delta_t.x * fabs(face_mask.x);
|
|
intersection_t.y += delta_t.y * fabs(face_mask.y);
|
|
intersection_t.z += delta_t.z * fabs(face_mask.z);
|
|
|
|
voxel.x += voxel_step.x * face_mask.x;
|
|
voxel.y += voxel_step.y * face_mask.y;
|
|
voxel.z += voxel_step.z * face_mask.z;
|
|
|
|
if (voxel.x >= map_dim->x || voxel.y >= map_dim->y || voxel.z >= map_dim->z) {
|
|
return travel_path;
|
|
}
|
|
if (voxel.x < 0 || voxel.y < 0 || voxel.z < 0) {
|
|
return travel_path;
|
|
}
|
|
|
|
// If we hit a voxel
|
|
voxel_data = map[voxel.x + (*map_dim).x * (voxel.y + (*map_dim).z * (voxel.z))];
|
|
|
|
travel_path.push_back(std::make_tuple(voxel, voxel_data));
|
|
|
|
if (voxel_data != 0)
|
|
return travel_path;
|
|
|
|
|
|
} while (++dist < 700.0f);
|
|
|
|
return travel_path;
|
|
} |