Removed the class heirarchy for the raycaster. I was aiming for maximum compatability but realistically, this project will never run at any sort of acceptable speed on the cpu. Also in the previous commit fixed multiple longterm bugs as well as fixed bugs in the event system and made it much safer

master
MitchellHansen 8 years ago
parent 334a375535
commit a40b5545e8

@ -4,7 +4,6 @@
#include <numeric> #include <numeric>
#include "util.hpp" #include "util.hpp"
#include "Pub_Sub.h" #include "Pub_Sub.h"
#include "raycaster/RayCaster.h"
#include "raycaster/Hardware_Caster.h" #include "raycaster/Hardware_Caster.h"
#include "LightHandle.h" #include "LightHandle.h"

@ -1,5 +1,4 @@
#pragma once #pragma once
#include <raycaster/RayCaster.h>
#include <Vector4.hpp> #include <Vector4.hpp>
#include <vector> #include <vector>
#include <iostream> #include <iostream>

@ -1,55 +0,0 @@
#pragma once
#include "Vector4.hpp"
#include <map/Map.h>
#include <SFML/Graphics.hpp>
class Old_Map;
class Camera;
struct PackedData;
class RayCaster {
public:
enum ERROR_CODES {
SHARING_NOT_SUPPORTED = 800,
OPENCL_NOT_SUPPORTED = 801,
OPENCL_ERROR = 802,
ERR = 803
};
RayCaster();
virtual ~RayCaster();
virtual int init() = 0;
virtual void assign_map(Old_Map *map) = 0;
virtual void assign_camera(Camera *camera) = 0;
virtual void create_viewport(int width, int height, float v_fov, float h_fov) = 0;
virtual void assign_lights(std::vector<PackedData> *data) = 0;
virtual void validate() = 0;
// draw will abstract the gl sharing and software rendering
// methods of retrieving the screen buffer
virtual void compute() = 0;
virtual void draw(sf::RenderWindow* window) = 0;
protected:
sf::Sprite viewport_sprite;
sf::Texture viewport_texture;
Old_Map * map = nullptr;
Camera *camera = nullptr;
// std::vector<LightController::PackedData> *lights;
std::vector<PackedData> *lights;
int light_count = 0;
sf::Uint8 *viewport_image = nullptr;
sf::Vector4f *viewport_matrix = nullptr;
sf::Vector2i viewport_resolution;
int error = 0;
};

@ -1,40 +0,0 @@
#pragma once
#include "raycaster/RayCaster.h"
#include <thread>
#include "map/Old_Map.h"
#include "Camera.h"
struct PackedData;
class Software_Caster : public RayCaster
{
public:
Software_Caster();
virtual ~Software_Caster();
int init() override;
// In interop mode, this will create a GL texture that we share
// Otherwise, it will create the pixel buffer and pass that in as an image, retrieving it each draw
// Both will create the view matrix, view res buffer
void create_viewport(int width, int height, float v_fov, float h_fov) override;
void assign_lights(std::vector<PackedData> *data) override;
void assign_map(Old_Map *map) override;
void assign_camera(Camera *camera) override;
void validate() override;
// draw will abstract the gl sharing and software rendering
// methods of retrieving the screen buffer
void compute() override;
void draw(sf::RenderWindow* window) override;
private:
void cast_viewport();
void cast_thread(int start_id, int end_id);
void cast_ray(int id);
void blit_pixel(sf::Color color, sf::Vector2i position, sf::Vector3i mask);
sf::Color global_light(sf::Color in, sf::Vector3i mask);
};

@ -54,7 +54,6 @@ int Camera::add_relative_impulse(DIRECTION impulse_direction, float speed) {
} }
std::cout << movement.x << " : " << movement.y << " : " << movement.z << std::endl;
movement += SphereToCart(dir) * speed; movement += SphereToCart(dir) * speed;
return 1; return 1;

@ -112,7 +112,6 @@ void Input::handle_held_keys() {
void Input::dispatch_events() { void Input::dispatch_events() {
std::cout << event_queue.size() << std::endl;
while (event_queue.size() != 0) { while (event_queue.size() != 0) {
notify_subscribers(std::move(event_queue.front())); notify_subscribers(std::move(event_queue.front()));
event_queue.pop_front(); event_queue.pop_front();

@ -29,7 +29,6 @@
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
#include <SFML/Network.hpp> #include <SFML/Network.hpp>
#include "map/Old_Map.h" #include "map/Old_Map.h"
#include "raycaster/RayCaster.h"
#include "raycaster/Hardware_Caster.h" #include "raycaster/Hardware_Caster.h"
#include "Vector4.hpp" #include "Vector4.hpp"
#include "Camera.h" #include "Camera.h"
@ -39,6 +38,7 @@
#include "LightHandle.h" #include "LightHandle.h"
#include "imgui/imgui-SFML.h" #include "imgui/imgui-SFML.h"
#include "imgui/imgui.h" #include "imgui/imgui.h"
#include "map/Map.h"
const int WINDOW_X = 1536; const int WINDOW_X = 1536;
const int WINDOW_Y = 1024; const int WINDOW_Y = 1024;

@ -1002,16 +1002,16 @@ bool Hardware_Caster::vr_assert(int error_code, std::string function_name) {
case CL_PLATFORM_NOT_FOUND_KHR : case CL_PLATFORM_NOT_FOUND_KHR :
err_msg = "CL_PLATFORM_NOT_FOUND_KHR"; err_msg = "CL_PLATFORM_NOT_FOUND_KHR";
break; break;
case RayCaster::SHARING_NOT_SUPPORTED: case Hardware_Caster::SHARING_NOT_SUPPORTED:
err_msg = "SHARING_NOT_SUPPORTED"; err_msg = "SHARING_NOT_SUPPORTED";
break; break;
case RayCaster::OPENCL_NOT_SUPPORTED: case Hardware_Caster::OPENCL_NOT_SUPPORTED:
err_msg = "OPENCL_NOT_SUPPORTED"; err_msg = "OPENCL_NOT_SUPPORTED";
break; break;
case RayCaster::OPENCL_ERROR: case Hardware_Caster::OPENCL_ERROR:
err_msg = "OPENCL_ERROR"; err_msg = "OPENCL_ERROR";
break; break;
case RayCaster::ERR: case Hardware_Caster::ERR:
err_msg = "ERROR"; err_msg = "ERROR";
break; break;
} }

@ -1,7 +0,0 @@
#include "raycaster/RayCaster.h"
RayCaster::RayCaster() {
}
RayCaster::~RayCaster() {
}

@ -1,343 +0,0 @@
#include "raycaster/Software_Caster.h"
Software_Caster::Software_Caster()
{
}
Software_Caster::~Software_Caster()
{
}
int Software_Caster::init()
{
return 1;
}
void Software_Caster::create_viewport(int width, int height, float v_fov, float h_fov)
{
// CL needs the screen resolution
viewport_resolution = sf::Vector2i(width, height);
// And an array of vectors describing the way the "lens" of our
// camera works
// This could be modified to make some odd looking camera lenses
double y_increment_radians = DegreesToRadians(v_fov / viewport_resolution.y);
double x_increment_radians = DegreesToRadians(h_fov / viewport_resolution.x);
viewport_matrix = new sf::Vector4f[width * height * 4];
for (int y = -viewport_resolution.y / 2; y < viewport_resolution.y / 2; y++) {
for (int x = -viewport_resolution.x / 2; x < viewport_resolution.x / 2; x++) {
// The base ray direction to slew from
sf::Vector3f ray(1, 0, 0);
// Y axis, pitch
ray = sf::Vector3f(
static_cast<float>(ray.z * sin(y_increment_radians * y) + ray.x * cos(y_increment_radians * y)),
static_cast<float>(ray.y),
static_cast<float>(ray.z * cos(y_increment_radians * y) - ray.x * sin(y_increment_radians * y))
);
// Z axis, yaw
ray = sf::Vector3f(
static_cast<float>(ray.x * cos(x_increment_radians * x) - ray.y * sin(x_increment_radians * x)),
static_cast<float>(ray.x * sin(x_increment_radians * x) + ray.y * cos(x_increment_radians * x)),
static_cast<float>(ray.z)
);
int index = (x + viewport_resolution.x / 2) + viewport_resolution.x * (y + viewport_resolution.y / 2);
ray = Normalize(ray);
viewport_matrix[index] = sf::Vector4f(
ray.x,
ray.y,
ray.z,
0
);
}
}
// Create the image that opencl's rays write to
viewport_image = new sf::Uint8[width * height * 4];
for (int i = 0; i < width * height * 4; i += 4) {
viewport_image[i] = 255; // R
viewport_image[i + 1] = 255; // G
viewport_image[i + 2] = 255; // B
viewport_image[i + 3] = 255; // A
}
// Interop lets us keep a reference to it as a texture
viewport_texture.create(width, height);
viewport_texture.update(viewport_image);
viewport_sprite.setTexture(viewport_texture);
}
void Software_Caster::assign_lights(std::vector<PackedData> *data) {
// this->lights = data;
// int light_count = static_cast<int>(data->size());
}
void Software_Caster::assign_map(Old_Map * map) {
this->map = map;
}
void Software_Caster::assign_camera(Camera * camera) {
this->camera = camera;
}
void Software_Caster::validate() {
// Check to make sure everything has been entered;
if (camera == nullptr ||
map == nullptr ||
viewport_image == nullptr ||
viewport_matrix == nullptr) {
std::cout << "Raycaster.validate() failed, camera, map, or viewport not initialized";
}
}
void Software_Caster::compute() {
cast_viewport();
}
void Software_Caster::draw(sf::RenderWindow * window) {
viewport_texture.update(viewport_image);
window->draw(viewport_sprite);
}
void Software_Caster::cast_viewport() {
std::vector<std::thread*> threads;
for (int i = 0; i < 13; i++) {
int s = viewport_resolution.x * ((viewport_resolution.y / 13) * i);
int e = viewport_resolution.x * ((viewport_resolution.y / 13) * (i + 1));
threads.push_back(new std::thread(&Software_Caster::cast_thread, this, s, e));
}
for (auto i : threads) {
i->join();
delete i;
}
}
void Software_Caster::cast_thread(int start_id, int end_id) {
for (int i = start_id; i < end_id; i++) {
cast_ray(i);
}
}
void Software_Caster::cast_ray(int id)
{
sf::Vector2i pixel = { id % viewport_resolution.x, id / viewport_resolution.x };
// 4f 3f ??
sf::Vector4f ray_dir = viewport_matrix[pixel.x + viewport_resolution.x * pixel.y];
ray_dir = sf::Vector4f(
ray_dir.z * sin(camera->get_direction().x) + ray_dir.x * cos(camera->get_direction().x),
ray_dir.y,
ray_dir.z * cos(camera->get_direction().x) - ray_dir.x * sin(camera->get_direction().x),
0
);
ray_dir = sf::Vector4f(
ray_dir.x * cos(camera->get_direction().y) - ray_dir.y * sin(camera->get_direction().y),
ray_dir.x * sin(camera->get_direction().y) + ray_dir.y * cos(camera->get_direction().y),
ray_dir.z,
0
);
// Setup the voxel step based on what direction the ray is pointing
sf::Vector3i voxel_step = sf::Vector3i(
static_cast<int>(1 * (abs(ray_dir.x) / ray_dir.x)),
static_cast<int>(1 * (abs(ray_dir.y) / ray_dir.y)),
static_cast<int>(1 * (abs(ray_dir.z) / ray_dir.z))
);
// Setup the voxel coords from the camera origin
sf::Vector3i voxel = sf::Vector3i(
static_cast<int>(camera->get_position().x),
static_cast<int>(camera->get_position().y),
static_cast<int>(camera->get_position().z)
);
// Delta T is the units a ray must travel along an axis in order to
// traverse an integer split
sf::Vector3f delta_t = sf::Vector3f(
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
sf::Vector3f offset = sf::Vector3f(
(camera->get_position().x - floor(camera->get_position().x)) * voxel_step.x,
(camera->get_position().y - floor(camera->get_position().y)) * voxel_step.y,
(camera->get_position().z - floor(camera->get_position().z)) * voxel_step.z
);
// Intersection T is the collection of the next intersection points
// for all 3 axis XYZ.
sf::Vector3f intersection_t = sf::Vector3f(
delta_t.x * offset.x,
delta_t.y * offset.y,
delta_t.z * offset.z
);
// for negative values, wrap around the delta_t, rather not do this
// component wise, but it doesn't appear to want to work
if (intersection_t.x < 0) {
intersection_t.x += delta_t.x;
}
if (intersection_t.y < 0) {
intersection_t.y += delta_t.y;
}
if (intersection_t.z < 0) {
intersection_t.z += delta_t.z;
}
// use a ghetto ass rng to give rays a "fog" appearance
sf::Vector2i randoms = { 3, 14 };
int seed = randoms.x + id;
int t = seed ^ (seed << 11);
int result = randoms.y ^ (randoms.y >> 19) ^ (t ^ (t >> 8));
int max_dist = 800 + result % 50;
int dist = 0;
sf::Vector3i mask = { 0, 0, 0 };
// Andrew Woo's raycasting algo
do {
if ((intersection_t.x) < (intersection_t.y)) {
if ((intersection_t.x) < (intersection_t.z)) {
mask.x = 1;
voxel.x += voxel_step.x;
intersection_t.x = intersection_t.x + delta_t.x;
}
else {
mask.z = 1;
voxel.z += voxel_step.z;
intersection_t.z = intersection_t.z + delta_t.z;
}
}
else {
if ((intersection_t.y) < (intersection_t.z)) {
mask.y = 1;
voxel.y += voxel_step.y;
intersection_t.y = intersection_t.y + delta_t.y;
}
else {
mask.z = 1;
voxel.z += voxel_step.z;
intersection_t.z = intersection_t.z + delta_t.z;
}
}
// If the ray went out of bounds
sf::Vector3i overshoot = sf::Vector3i(
voxel.x <= map->getDimensions().x,
voxel.y <= map->getDimensions().y,
voxel.z <= map->getDimensions().z
);
sf::Vector3i undershoot = sf::Vector3i(
voxel.x > 0,
voxel.y > 0,
voxel.z > 0
);
if (overshoot.x == 0 || overshoot.y == 0 || overshoot.z == 0 || undershoot.x == 0 || undershoot.y == 0) {
blit_pixel(sf::Color::Yellow, sf::Vector2i{ pixel.x,pixel.y }, mask);
return;
}
if (undershoot.z == 0) {
blit_pixel(sf::Color::Yellow, sf::Vector2i{ pixel.x,pixel.y }, mask);
return;
}
// If we hit a voxel
//int index = voxel.x * (*map_dim).y * (*map_dim).z + voxel.z * (*map_dim).z + voxel.y;
// Why the off by one on voxel.y?
int index = voxel.x + map->getDimensions().x * (voxel.y + map->getDimensions().z * (voxel.z - 1));
int voxel_data = map->get_voxel_data()[index];
if (voxel_data != 0) {
switch (voxel_data) {
case 1:
blit_pixel(sf::Color::Green, sf::Vector2i{ pixel.x,pixel.y }, mask);
return;
case 2:
blit_pixel(sf::Color::Green, sf::Vector2i{ pixel.x,pixel.y }, mask);
return;
case 3:
blit_pixel(sf::Color::Green, sf::Vector2i{ pixel.x,pixel.y }, mask);
return;
case 4:
blit_pixel(sf::Color::Green, sf::Vector2i{ pixel.x,pixel.y }, mask);
return;
case 5:
blit_pixel(sf::Color(30, 10, 200, 100), sf::Vector2i{ pixel.x,pixel.y }, mask);
return;
case 6:
blit_pixel(sf::Color::Green, sf::Vector2i{ pixel.x,pixel.y }, mask);
return;
default:
//write_imagef(image, pixel, (float4)(.30, .2550, .2550, 255.00));
return;
}
}
dist++;
} while (dist < max_dist);
blit_pixel(sf::Color::Red, sf::Vector2i{ pixel.x,pixel.y }, mask);
return;
}
void Software_Caster::blit_pixel(sf::Color color, sf::Vector2i position, sf::Vector3i mask) {
sf::Color t = global_light(color, mask);
viewport_image[(position.x + viewport_resolution.x * position.y) * 4 + 0] = t.r;
viewport_image[(position.x + viewport_resolution.x * position.y) * 4 + 1] = t.g;
viewport_image[(position.x + viewport_resolution.x * position.y) * 4 + 2] = t.b;
viewport_image[(position.x + viewport_resolution.x * position.y) * 4 + 3] = t.a;
}
sf::Color Software_Caster::global_light(sf::Color in, sf::Vector3i mask) {
// I think I may scrap this whole software fallback caster thing
//sf::Vector3f mask_f(mask);
//in.a = in.a + (int)acos(
// DotProduct(
// Normalize(lights->at(0).direction_cartesian),
// Normalize(mask_f)
// )
// )/ 2;
return in;
}
Loading…
Cancel
Save