diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/camera/camera.cpp | 33 | ||||
-rw-r--r-- | src/mainwindow.cpp | 14 | ||||
-rw-r--r-- | src/raytracer/raytracer.cpp | 90 | ||||
-rw-r--r-- | src/utils/sceneparser.cpp | 82 |
4 files changed, 151 insertions, 68 deletions
diff --git a/src/camera/camera.cpp b/src/camera/camera.cpp index 4c19663..b2d4b12 100644 --- a/src/camera/camera.cpp +++ b/src/camera/camera.cpp @@ -1,6 +1,7 @@ #include <stdexcept> #include "camera.h" #include "vec4ops/vec4ops.h" +#include "settings.h" Camera::Camera(SceneCameraData cameraData) : m_pos(cameraData.pos), @@ -8,11 +9,37 @@ Camera::Camera(SceneCameraData cameraData) : m_focalLength(cameraData.focalLength), m_aperture(cameraData.aperture) { - m_viewMatrix = Vec4Ops::getViewMatrix4(cameraData.pos, glm::vec4(0.f), cameraData.up, cameraData.look); - m_translationVector = glm::vec4{-cameraData.pos.x, -cameraData.pos.y, -cameraData.pos.z, -cameraData.pos.w}; + // m_viewMatrix = Vec4Ops::getViewMatrix4(cameraData.pos, glm::vec4(0.f), cameraData.up, cameraData.look); + // m_translationVector = glm::vec4{-cameraData.pos.x, -cameraData.pos.y, -cameraData.pos.z, -cameraData.pos.w}; + + // m_inverseViewMatrix = glm::inverse(m_viewMatrix); + // m_inverseTranslationVector = -m_translationVector; + glm::vec3 look3{cameraData.look.x, cameraData.look.y, cameraData.look.z}; + glm::vec3 up3{cameraData.up.x, cameraData.up.y, cameraData.up.z}; + + // calculate new basis + glm::vec3 e0 = -glm::normalize(look3); + glm::vec3 e1 = glm::normalize(up3 - glm::dot(up3, e0) * e0); + glm::vec3 e2 = glm::cross(e1, e0); + + glm::mat4 alignment + { + e2.x, e1.x, e0.x, 0.f, + e2.y, e1.y, e0.y, 0.f, + e2.z, e1.z, e0.z, 0.f, + 0.f, 0.f, 0.f, 1.f + }; + glm::mat4 translation + { + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + -cameraData.pos.x, -cameraData.pos.y, -cameraData.pos.z, 1.f + }; + + m_viewMatrix = alignment * translation; m_inverseViewMatrix = glm::inverse(m_viewMatrix); - m_inverseTranslationVector = -m_translationVector; } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index fafe7ad..959862d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -208,15 +208,15 @@ void MainWindow::initialize() { QHBoxLayout *lw = new QHBoxLayout(); wSlider = new QSlider(Qt::Orientation::Horizontal); // XY value slider - wSlider->setTickInterval(1); - wSlider->setMinimum(-5000); - wSlider->setMaximum(5000); + wSlider->setTickInterval(0.01); + wSlider->setMinimum(-500); + wSlider->setMaximum(500); wSlider->setValue(0); wBox = new QDoubleSpinBox(); - wBox->setMinimum(-50.0f); - wBox->setMaximum(50.f); - wBox->setSingleStep(1.f); + wBox->setMinimum(-5.0f); + wBox->setMaximum(5.f); + wBox->setSingleStep(0.01f); wBox->setValue(0.f); lw->addWidget(wSlider); @@ -247,6 +247,8 @@ void MainWindow::initialize() { connectUIElements(); + + onValChangeWSlider(0); } void MainWindow::finish() { diff --git a/src/raytracer/raytracer.cpp b/src/raytracer/raytracer.cpp index 8bcf6ba..acb229a 100644 --- a/src/raytracer/raytracer.cpp +++ b/src/raytracer/raytracer.cpp @@ -27,39 +27,39 @@ RayTracer::RayTracer(QWidget *parent) : QWidget(parent) { void RayTracer::render(RGBA *imageData, const RayTraceScene &scene) { if (m_enableParallelism) { renderParallel(imageData, scene); - } - - // naive rendering - Camera camera = scene.getCamera(); - float cameraDepth = 1.f; - - float viewplaneHeight = 2.f*cameraDepth*std::tan(camera.getHeightAngle() / 2.f); - float viewplaneWidth = cameraDepth*viewplaneHeight*((float)scene.width()/(float)scene.height()); - - for (int imageRow = 0; imageRow < scene.height(); imageRow++) { - for (int imageCol = 0; imageCol < scene.width(); imageCol++) { - // FIXME: for now, use height as depth - for (int imageDepth = 0; imageDepth < scene.height(); imageDepth++) { - // compute the ray - float x = (imageCol - scene.width()/2.f) * viewplaneWidth / scene.width(); - float y = (imageRow - scene.height()/2.f) * viewplaneHeight / scene.height(); - float z = (imageDepth - scene.height()/2.f) * viewplaneHeight / scene.height(); - float camera4dDepth = 1; - - glm::vec4 pWorld = Vec4Ops::transformPoint4(glm::vec4(x, y, z, 0.f), camera.getViewMatrix(), camera.getTranslationVector()); - glm::vec4 dWorld = glm::vec4(0.f, 0.f, 0.f, -1.f); - - // get the pixel color - glm::vec4 pixelColor = getPixelFromRay(pWorld, dWorld, scene, 0); - - // set the pixel color - int index = imageRow * scene.width() + imageCol; - imageData[index] = RGBA{ - (std::uint8_t) (pixelColor.r * 255.f), - (std::uint8_t) (pixelColor.g * 255.f), - (std::uint8_t) (pixelColor.b * 255.f), - (std::uint8_t) (pixelColor.a * 255.f) - }; + } else { + // naive rendering + Camera camera = scene.getCamera(); + float cameraDepth = 1.f; + + float viewplaneHeight = 2.f*cameraDepth*std::tan(camera.getHeightAngle() / 2.f); + float viewplaneWidth = cameraDepth*viewplaneHeight*((float)scene.width()/(float)scene.height()); + + for (int imageRow = 0; imageRow < scene.height(); imageRow++) { + for (int imageCol = 0; imageCol < scene.width(); imageCol++) { + // FIXME: for now, use height as depth + for (int imageDepth = 0; imageDepth < scene.height(); imageDepth++) { + // compute the ray + float x = (imageCol - scene.width()/2.f) * viewplaneWidth / scene.width(); + float y = (imageRow - scene.height()/2.f) * viewplaneHeight / scene.height(); + float z = (imageDepth - scene.height()/2.f) * viewplaneHeight / scene.height(); + float camera4dDepth = 1; + + glm::vec4 pWorld = Vec4Ops::transformPoint4(glm::vec4(x, y, z, 0.f), camera.getViewMatrix(), camera.getTranslationVector()); + glm::vec4 dWorld = glm::vec4(0.f, 0.f, 0.f, -1.f); + + // get the pixel color + glm::vec4 pixelColor = getPixelFromRay(pWorld, dWorld, scene, 0); + + // set the pixel color + int index = imageRow * scene.width() + imageCol; + imageData[index] = RGBA{ + (std::uint8_t) (pixelColor.r * 255.f), + (std::uint8_t) (pixelColor.g * 255.f), + (std::uint8_t) (pixelColor.b * 255.f), + (std::uint8_t) (pixelColor.a * 255.f) + }; + } } } } @@ -99,7 +99,7 @@ glm::vec4 RayTracer::getPixelFromRay( for (const RenderShapeData &shape : scene.getShapes()) { glm::vec4 pObject = shape.inverseCTM * pWorld; glm::vec4 dObject = glm::normalize(shape.inverseCTM * dWorld); - + std::cout << "pObject: " << pObject.w << std::endl; glm::vec4 newIntersectionObj = findIntersection(pObject, dObject, shape); if (newIntersectionObj.w == 0) // no hit { @@ -175,6 +175,11 @@ void RayTracer::sceneChanged(QLabel* imageLabel) { if (!success) { std::cerr << "Error loading scene: \"" << settings.sceneFilePath << "\"" << std::endl; + // return; + QImage image = QImage(576, 432, QImage::Format_RGBX8888); + image.fill(Qt::black); + RGBA *data = reinterpret_cast<RGBA *>(image.bits()); + imageLabel->setPixmap(QPixmap::fromImage(image)); return; } @@ -192,13 +197,26 @@ void RayTracer::sceneChanged(QLabel* imageLabel) { QImage flippedImage = image.mirrored(false, false); // make the image larger - flippedImage = flippedImage.scaled(2*width, 2*height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + flippedImage = flippedImage.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); imageLabel->setPixmap(QPixmap::fromImage(flippedImage)); m_imageLabel = imageLabel; } void RayTracer::settingsChanged(QLabel* imageLabel) { + bool success = SceneParser::parse(settings.sceneFilePath, m_metaData); + + if (!success) { + std::cerr << "Error loading scene: \"" << settings.sceneFilePath << "\"" << std::endl; + // return; + // render a blank image + QImage image = QImage(576, 432, QImage::Format_RGBX8888); + image.fill(Qt::black); + RGBA *data = reinterpret_cast<RGBA *>(image.bits()); + imageLabel->setPixmap(QPixmap::fromImage(image)); + return; + } + int width = 576; int height = 432; @@ -210,7 +228,7 @@ void RayTracer::settingsChanged(QLabel* imageLabel) { this->render(data, rtScene); QImage flippedImage = image.mirrored(false, false); - flippedImage = flippedImage.scaled(2*width, 2*height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + flippedImage = flippedImage.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); imageLabel->setPixmap(QPixmap::fromImage(flippedImage)); } diff --git a/src/utils/sceneparser.cpp b/src/utils/sceneparser.cpp index 5eddf93..009873b 100644 --- a/src/utils/sceneparser.cpp +++ b/src/utils/sceneparser.cpp @@ -4,6 +4,7 @@ #include <glm/gtx/transform.hpp> #include <QImage> #include <iostream> +#include "../settings.h" /** @@ -36,18 +37,28 @@ TextureData loadTextureFromFile(const QString &file) { // helper to handle recursive creation of tree void initTree(SceneNode* currentNode, std::vector<RenderShapeData> *shapes, std::vector<SceneLightData> *lights, glm::mat4 currentCTM, glm::vec4 currentTranslation4d) { + if (currentNode->transformations.size() == 0) { + // ScenePa.rser::translate4(currentTranslation4d, glm::vec4(0.f, 0.f, 0.f, settings.w)); + // convert currentTranslation4d to a 4x4 matrix + currentCTM = glm::translate(glm::mat4(1.0f), glm::vec3(currentTranslation4d)); + currentCTM *= SceneParser::getRotationMatrix4(1.f, glm::vec3(settings.xy, settings.xz, settings.yz), glm::vec3(settings.xw, settings.yw, settings.zw)); + } + + SceneParser::translate4(currentTranslation4d, glm::vec4(0.f, 0.f, 0.f, settings.w)); + for (auto t : currentNode->transformations) { switch (t->type) { case TransformationType::TRANSFORMATION_TRANSLATE: - SceneParser::translate4(currentTranslation4d, t->translate); - break; - case TransformationType::TRANSFORMATION_SCALE: - SceneParser::scale4(currentCTM, t->scale); + SceneParser::translate4(currentTranslation4d, glm::vec4(t->translate.xyz(), 0.f)); + // currentCTM = glm::translate(glm::mat4(1.0f), glm::vec3(currentTranslation4d)); break; case TransformationType::TRANSFORMATION_ROTATE: currentCTM *= SceneParser::getRotationMatrix4(t->angle, t->rotate3, t->rotateW); break; + case TransformationType::TRANSFORMATION_SCALE: + SceneParser::scale4(currentCTM, t->scale); + break; case TransformationType::TRANSFORMATION_MATRIX: currentCTM *= glm::mat4(t->matrix); currentTranslation4d *= glm::vec4(t->matrixRight4d); // TODO @@ -58,6 +69,8 @@ void initTree(SceneNode* currentNode, std::vector<RenderShapeData> *shapes, std: } } + currentCTM *= glm::translate(glm::mat4(1.0f), glm::vec3(currentTranslation4d)); + for(auto primitive : currentNode->primitives) { // primitive->material.textureData = loadTextureFromFile(QString::fromStdString(primitive->material.textureMap.filename)); @@ -144,25 +157,48 @@ bool SceneParser::parse(std::string filepath, RenderData &renderData) { return true; } -glm::mat4 SceneParser::getRotationMatrix4( - float angle, - glm::vec3 axis3, - glm::vec3 axisW) { - // start with the normal rotation from the normal 3d axes - if (axis3.x > 0) - return Vec4Ops::getRotationMatrix4XY(angle); - else if (axis3.y > 0) - return Vec4Ops::getRotationMatrix4YZ(angle); - else if (axis3.z > 0) - return Vec4Ops::getRotationMatrix4ZX(angle); - else if (axisW.x > 0) - return Vec4Ops::getRotationMatrix4XW(angle); - else if (axisW.y > 0) - return Vec4Ops::getRotationMatrix4YW(angle); - else if (axisW.z > 0) - return Vec4Ops::getRotationMatrix4ZW(angle); - else - throw std::runtime_error("invalid axis"); +// glm::mat4 SceneParser::getRotationMatrix4( +// float angle, +// glm::vec3 axis3, +// glm::vec3 axisW) { +// // start with the normal rotation from the normal 3d axes +// if (axis3.x > 0) +// return Vec4Ops::getRotationMatrix4XY(angle); +// else if (axis3.y > 0) +// return Vec4Ops::getRotationMatrix4YZ(angle); +// else if (axis3.z > 0) +// return Vec4Ops::getRotationMatrix4ZX(angle); +// else if (axisW.x > 0) +// return Vec4Ops::getRotationMatrix4XW(angle); +// else if (axisW.y > 0) +// return Vec4Ops::getRotationMatrix4YW(angle); +// else if (axisW.z > 0) +// return Vec4Ops::getRotationMatrix4ZW(angle); +// else +// throw std::runtime_error("invalid axis"); +// } + +glm::mat4 SceneParser::getRotationMatrix4(float angle, glm::vec3 axis3, glm::vec3 axisW) { + glm::mat4 rotationMatrix3D = glm::mat4(1.0f); // Identity matrix + + // convert axis3 and axisW to radians + axis3 = glm::radians(axis3); + axisW = glm::radians(axisW); + + // Apply 3D rotations if any axis is non-zero + if (axis3.x != 0) rotationMatrix3D *= glm::rotate(axis3.x, glm::vec3(1, 0, 0)); + if (axis3.y != 0) rotationMatrix3D *= glm::rotate(axis3.y, glm::vec3(0, 1, 0)); + if (axis3.z != 0) rotationMatrix3D *= glm::rotate(axis3.z, glm::vec3(0, 0, 1)); + + glm::mat4 rotationMatrix4D = glm::mat4(1.0f); // Identity matrix + + // Apply 4D rotations if any axis is non-zero + if (axisW.x != 0) rotationMatrix4D *= Vec4Ops::getRotationMatrix4XW(axisW.x); + if (axisW.y != 0) rotationMatrix4D *= Vec4Ops::getRotationMatrix4YW(axisW.y); + if (axisW.z != 0) rotationMatrix4D *= Vec4Ops::getRotationMatrix4ZW(axisW.z); + + // Combine both 3D and 4D rotations + return rotationMatrix4D * rotationMatrix3D; } void SceneParser::translate4( |