diff --git a/src/definitions/camera.cpp b/src/definitions/camera.cpp index 5d3793f..472ae92 100644 --- a/src/definitions/camera.cpp +++ b/src/definitions/camera.cpp @@ -1,30 +1,42 @@ #include "camera.hpp" -Camera::Camera(glm::vec3 point, glm::vec3 dir, float w, float h, float f) { - point = { 0.0f, 0.0f, 0.0f }; - point = point; - direction = dir; - w = w; h = h; focalLen = f; +#include "ray.hpp" + +Camera::Camera(int width, int height) + : position({0,0,0}), + direction({0,0,1}), + right({(float)width/(float)height,0,0}), + up({0,1,0}) { } + +Camera::Camera(glm::vec3 position, glm::vec3 direction, glm::vec3 right, glm::vec3 up) + : position(position), direction(direction), right(right), up(up) { } + +Camera::Camera(glm::vec3 position, int width, int height) + : position(position), + direction({0,0,1}), + right({(float)width/(float)height,0,0}), + up({0,1,0}) { } + +void Camera::LookAt(glm::vec3 position, glm::vec3 sky, glm::vec3 lookAt, float angle, int width, int height) { + float rightL = width / (float) height; + float dirL = 0.5f * rightL / tan(angle / 2.0f); + + direction = glm::normalize(glm::vec3 {position.x - lookAt.x, position.y - lookAt.y, position.z - lookAt.z}) * dirL; + right = glm::normalize(glm::cross(sky, direction)) * rightL; + up = glm::normalize(glm::cross(direction, right)); } -void Camera::Update() { - glm::vec3 up = {0.0f, -1.0f, 0.0f}; - glm::vec3 c0 = point + (direction * focalLen); - glm::vec3 uX = glm::normalize(glm::cross(direction, up)); - glm::vec3 uY = glm::cross((direction * -1.0f), uX); - planeCenter = c0; - planeDirX = uX; - planeDirY = uY; - - // Vector3 x_c = c->position; - // Vector3 u_c = c->direction; - // double z_p = c->focalLength; - // Vector3 v_up = vec3_make(0.0, -1.0, 0.0); - // Vector3 c_0 = vec3_add(position, vec3_mult(direction, focalLength)); - // Vector3 u_x = vec3_unit(vec3_cross(direction, v_up)); - // Vector3 u_y = vec3_cross(vec3_mult(direction, -1.0), u_x); - // c->planeCenter = c_0; - // c->planeDirectionX = u_x; - // c->planeDirectionY = u_y; - // Vector3 u_z = vec3_mult(direction, -1.0); // Normal to the view plane +Ray Camera::CastRay(int x, int y, float spX, float spY) { + // TODO: ACTUALLY GET A WORKING CAMERA + float camX = (((float)x + spX) / (float)600 * 2.0f - 1.0f) * getAspectRatio(600, 600) * getFovAdjustment(45.0f); + // 1.0 is taken first here as y is in the vertical + float camY = (1.0f - ((float)y + spY) / (float)600 * 2.0f) * getFovAdjustment(45.0f); + Ray ray{ {0.0f, 0.0f, 0.0f}, {camX, camY, -1.0f} }; + ray.direction = glm::normalize(ray.direction); + + return ray; + + // glm::vec3 value = direction + (right * ((float)x + spX)) + (up * ((float)y + spY)); + // glm::normalize(value); + // return {position, value}; } diff --git a/src/definitions/camera.hpp b/src/definitions/camera.hpp index 834ced4..d8384a6 100644 --- a/src/definitions/camera.hpp +++ b/src/definitions/camera.hpp @@ -3,18 +3,20 @@ #include "../maths.hpp" +class Ray; + class Camera { public: - Camera(glm::vec3 point, glm::vec3 dir, float w, float h, float f = 500.0f); + Camera(int width, int height); + Camera(glm::vec3 position, glm::vec3 direction, glm::vec3 right, glm::vec3 up); + Camera(glm::vec3 position, int width, int height); - void Update(); + void LookAt(glm::vec3 position, glm::vec3 sky, glm::vec3 lookAt, float angle, int width, int height); - glm::vec3 point = {}; - glm::vec3 direction = {}; - glm::vec3 planeCenter = {}; - glm::vec3 planeDirX = {}; - glm::vec3 planeDirY = {}; - float focalLen, w, h; + Ray CastRay(int x, int y, float spX = 0.5f, float spY = 0.5f); + + glm::vec3 position; + glm::vec3 direction, right, up; }; #endif diff --git a/src/definitions/primatives/plane.cpp b/src/definitions/primatives/plane.cpp new file mode 100644 index 0000000..dea6c03 --- /dev/null +++ b/src/definitions/primatives/plane.cpp @@ -0,0 +1,33 @@ +#include "plane.hpp" +#include "../ray.hpp" + +bool Plane::DoesIntersect(Ray& ray, float& t) { + t = INFINITY; + float dNormal = glm::dot(normal, ray.direction); + if (dNormal > 1e-6) { + glm::vec3 v = center - ray.origin; + float distance = glm::dot(v, normal) / dNormal; + if (distance >= 0.0f) { + t = distance; + return true; + } + } + return false; +} + +glm::vec3 Plane::SurfaceNormal(glm::vec3 hitPoint) { + return -normal; +} + +glm::vec2 Plane::TexCoords(glm::vec3 hitPoint) { + glm::vec3 xAxis = glm::cross(normal, { 0.0f, 0.0f, 1.0f }); + if (xAxis.length() == 0.0f) xAxis = glm::cross(normal, { 0.0f, 1.0f, 0.0f }); + glm::vec3 yAxis = glm::cross(normal, xAxis); + + glm::vec3 hit = hitPoint - center; + return { glm::dot(hit, xAxis), glm::dot(hit, yAxis) }; +} + +void Plane::Translate(glm::vec3 trans) { + center += trans; +} diff --git a/src/definitions/primatives/plane.hpp b/src/definitions/primatives/plane.hpp new file mode 100644 index 0000000..6bc6613 --- /dev/null +++ b/src/definitions/primatives/plane.hpp @@ -0,0 +1,17 @@ +#ifndef INFERNO_DEFINITIONS_PRIMATIVES_PLANE_H_ +#define INFERNO_DEFINITIONS_PRIMATIVES_PLANE_H_ + +#include "primative.hpp" + +class Plane : public Primative { +public: + Plane(glm::vec3 center, glm::vec3 normal) + : Primative(center, normal) { } + + bool DoesIntersect(Ray& ray, float& t) override; + glm::vec3 SurfaceNormal(glm::vec3 hitPoint) override; + glm::vec2 TexCoords(glm::vec3 hitPoint) override; + void Translate(glm::vec3 trans) override; +}; + +#endif diff --git a/src/definitions/ray.cpp b/src/definitions/ray.cpp index 75f8675..ed8f3de 100644 --- a/src/definitions/ray.cpp +++ b/src/definitions/ray.cpp @@ -1,24 +1 @@ #include "ray.hpp" - -#include "camera.hpp" -#include "scene.hpp" - -Ray GeneratePrimaryRay(int x, int y, Scene* scene, float xSubPix, float ySubPix) { - Camera* cam = scene->camera; - float dy = 1.0f; - float dx = 1.0f; - float px = (-(float)cam->w / 2.0f) + dx * ((float)x + xSubPix); - float py = (-(float)cam->h / 2.0f) + dy * ((float)y + ySubPix); - glm::vec3 p = cam->planeCenter + (cam->planeDirX * px) + (cam->planeDirY * py); - glm::vec3 dir = glm::normalize(p - cam->point); - return {cam->point, dir}; - // double dy = 1.0; - // double dx = 1.0; - // double px = (- c->width / 2.0) + dx * ((double)x + 0.5); - // double py = (- c->height / 2.0) + dy * ((double)y + 0.5); - // Vector3 p = vec3_add3(c->planeCenter, - // vec3_mult(c->planeDirectionX, px), - // vec3_mult(c->planeDirectionY, py)); - // Vector3 u_r = vec3_unit(vec3_sub(p, c->position)); - // return ray_make(c->position, u_r); -} diff --git a/src/definitions/ray.hpp b/src/definitions/ray.hpp index f75007b..51cfe0a 100644 --- a/src/definitions/ray.hpp +++ b/src/definitions/ray.hpp @@ -7,10 +7,8 @@ class Scene; class Ray { public: - glm::vec3 origin; - glm::vec3 direction; + glm::vec3 origin = {}; + glm::vec3 direction = {}; }; -Ray GeneratePrimaryRay(int x, int y, Scene* scene, float xSubPix = 0.5f, float ySubPix = 0.5f); - #endif diff --git a/src/display/display.cpp b/src/display/display.cpp index 245e538..f89a681 100644 --- a/src/display/display.cpp +++ b/src/display/display.cpp @@ -52,7 +52,7 @@ bool Display::InitVideoDisplay(std::string title, int x, int y) { } Framebuffer = (uint32_t*)malloc(this->XRes * this->YRes * sizeof(uint32_t)); - + memset((void*)Framebuffer, 0, this->XRes * this->YRes * sizeof(uint32_t)); if (!Framebuffer) { // Add error std::cout << "ERROR: COULD NOT ALLOCATE FRAMEBUFFER" << std::endl; @@ -92,6 +92,7 @@ void Display::Update() { SDL_UpdateTexture(m_texture, NULL, Framebuffer, this->XRes * sizeof(uint32_t)); SDL_RenderCopy(m_renderer, m_texture, NULL, NULL); SDL_RenderPresent(m_renderer); + memset((void*)Framebuffer, 0, this->XRes * this->YRes * sizeof(uint32_t)); } void Display::Close() { diff --git a/src/engine/progressiverenderer.cpp b/src/engine/progressiverenderer.cpp index daa37dd..61719d3 100644 --- a/src/engine/progressiverenderer.cpp +++ b/src/engine/progressiverenderer.cpp @@ -26,17 +26,19 @@ void ProgressiveRenderer::Render() { while (SDL_PollEvent(&e)) if (e.type == SDL_QUIT) m_interface->Close(); - // Update the camera - m_scene->camera->Update(); - for (int x = 0; x < m_scene->w; x++) for (int y = 0; y < m_scene->h; y++) { - Ray ray = GeneratePrimaryRay(x, y, m_scene); + Ray ray = m_scene->camera->CastRay(x, y); for (int i = 0; i < m_scene->objects.size(); i++) { + Primative* smh = m_scene->objects[i]; float t = 0; - if (m_scene->objects[i]->DoesIntersect(ray, t)) { - m_interface->SetPixelSafe(x, y, rgb888(0, 255, 0)); + if (smh->DoesIntersect(ray, t)) { + if (smh->type == TYPE_SPHERE) { + m_interface->SetPixelSafe(x, y, 0x00FF00); + } else { + m_interface->SetPixelSafe(x, y, 0x00FFFF); + } } } } diff --git a/src/inferno.hpp b/src/inferno.hpp index 79793d1..84db6bc 100644 --- a/src/inferno.hpp +++ b/src/inferno.hpp @@ -11,6 +11,7 @@ #include "definitions/scene.hpp" #include "definitions/camera.hpp" #include "definitions/primatives/sphere.hpp" +#include "definitions/primatives/plane.hpp" class Display; class Renderer; diff --git a/src/maths.hpp b/src/maths.hpp index 3649279..8039748 100644 --- a/src/maths.hpp +++ b/src/maths.hpp @@ -2,6 +2,10 @@ #define INFERNO_MATHS_H_ #include +#include +#include +#include + #include #include diff --git a/test/main.cpp b/test/main.cpp index fa6e6d8..328c27f 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -12,8 +12,9 @@ int main(int argc, char** argv) { } Scene* scene = new Scene(600, 600); - scene->camera = new Camera({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, 600, 600); - scene->objects.push_back(new Sphere({0.0f, 0.0f, 2.0f}, 1.0f)); + scene->camera = new Camera(600, 600); + scene->objects.push_back(new Plane({0.0f, -0.5f, 0.0f}, {0.0f, -1.0f, 0.0f})); + scene->objects.push_back(new Sphere({0.0f, 0.0f, -4.0f}, 1.0f)); inferno.SetScene(scene);