aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/accelerate/myqtconcurrent.cpp29
-rw-r--r--src/illuminate/shadow.cpp4
-rw-r--r--src/main.cpp172
-rw-r--r--src/mainwindow.cpp384
-rw-r--r--src/mainwindow.h66
-rw-r--r--src/raytracer/raytracer.cpp62
-rw-r--r--src/raytracer/raytracer.h26
-rw-r--r--src/settings.cpp3
-rw-r--r--src/settings.h21
-rw-r--r--src/utils/aspectratiowidget/aspectratiowidget.hpp66
-rw-r--r--src/utils/sceneparser.cpp2
11 files changed, 737 insertions, 98 deletions
diff --git a/src/accelerate/myqtconcurrent.cpp b/src/accelerate/myqtconcurrent.cpp
index 1dff0e0..aeb160b 100644
--- a/src/accelerate/myqtconcurrent.cpp
+++ b/src/accelerate/myqtconcurrent.cpp
@@ -1,13 +1,13 @@
#include <QList>
#include <QtConcurrent>
-#include "raytracer/raytracer.h"
+#include "../raytracer/raytracer.h"
struct pixelRoutineArgs {
glm::vec4 pCamera;
glm::vec4 dCamera;
const RayTraceScene &scene;
- RayTracer rt;
+ RayTracer *rt;
};
static RGBA pixelRoutine(pixelRoutineArgs args);
@@ -28,12 +28,13 @@ void RayTracer::renderParallel(RGBA *imageData, const RayTraceScene &scene)
glm::vec4 pixelDirCamera{xCameraSpace, -yCameraSpace, -cameraDepth, 0.f}; //w=0 for dir
glm::vec4 eyeCamera{0.f, 0.f, 0.f, 1.f}; // w=1.f for point
- l.append({
- eyeCamera, // eye
- pixelDirCamera, // direction
- scene,
- *this
- });
+ pixelRoutineArgs args{
+ eyeCamera,
+ pixelDirCamera,
+ scene,
+ this
+ };
+ l.append(args);
}
}
@@ -44,7 +45,7 @@ void RayTracer::renderParallel(RGBA *imageData, const RayTraceScene &scene)
imageData[index++] = p;
}
- if (m_config.enableAntiAliasing)
+ if (m_enableAntiAliasing)
{
filterBlur(imageData, scene.width(), scene.height());
}
@@ -63,18 +64,18 @@ RGBA pixelRoutine(pixelRoutineArgs args)
glm::vec4 pWorld = inv * eyeCamera;
glm::vec4 dWorld = glm::normalize(inv * pixelDirCamera);
- if (rt.m_config.enableDepthOfField)
+ if (rt->m_enableDepthOfField)
{
// if we're doing depth of field, we need to shoot multiple rays, see camera.cpp
- return RayTracer::toRGBA(rt.secondaryRays(pWorld, dWorld, scene));
+ return RayTracer::toRGBA(rt->secondaryRays(pWorld, dWorld, scene));
}
- if (rt.m_config.enableSuperSample)
+ if (rt->m_enableSuperSample)
{
// if we're doing super sampling, we need to shoot multiple rays, see raytracer.cpp
- return rt.superSample(eyeCamera, pixelDirCamera, scene);
+ return rt->superSample(eyeCamera, pixelDirCamera, scene);
}
// shoot ray!
- RGBA pixel = RayTracer::toRGBA(rt.getPixelFromRay(pWorld, dWorld, scene, 0));
+ RGBA pixel = RayTracer::toRGBA(rt->getPixelFromRay(pWorld, dWorld, scene, 0));
return pixel;
}
diff --git a/src/illuminate/shadow.cpp b/src/illuminate/shadow.cpp
index 99e2b29..efb52a7 100644
--- a/src/illuminate/shadow.cpp
+++ b/src/illuminate/shadow.cpp
@@ -11,7 +11,7 @@ bool RayTracer::isShadowed(
directionFromIntersectionToLight = glm::normalize(directionFromIntersectionToLight);
// acceleration causes "bad jaggies" so we disable it for now
- if (m_config.enableAcceleration)
+ if (m_enableAcceleration)
{
RenderShapeData shapeData;
auto pBias = intersectionWorld + .001f * directionFromIntersectionToLight;
@@ -55,4 +55,4 @@ bool RayTracer::isShadowed(
}
return false;
-} \ No newline at end of file
+}
diff --git a/src/main.cpp b/src/main.cpp
index 8cb00b8..29828d8 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2,85 +2,111 @@
#include <QCommandLineParser>
#include <QImage>
#include <QtCore>
+#include <QApplication>
+#include <QScreen>
+#include <iostream>
+#include <QSettings>
+#include <QSurfaceFormat>
#include <iostream>
#include "utils/sceneparser.h"
#include "raytracer/raytracer.h"
#include "raytracer/raytracescene.h"
+#include "mainwindow.h"
+
int main(int argc, char *argv[])
{
- QCoreApplication a(argc, argv);
-
- QCommandLineParser parser;
- parser.addHelpOption();
- parser.addPositionalArgument("config", "Path of the config file.");
- parser.process(a);
-
- auto positionalArgs = parser.positionalArguments();
- if (positionalArgs.size() != 1) {
- std::cerr << "Not enough arguments. Please provide a path to a config file (.ini) as a command-line argument." << std::endl;
- a.exit(1);
- return 1;
- }
-
- QSettings settings( positionalArgs[0], QSettings::IniFormat );
- QString iScenePath = settings.value("IO/scene").toString();
- QString oImagePath = settings.value("IO/output").toString();
-
- RenderData metaData;
- bool success = SceneParser::parse(iScenePath.toStdString(), metaData);
-
- if (!success) {
- std::cerr << "Error loading scene: \"" << iScenePath.toStdString() << "\"" << std::endl;
- a.exit(1);
- return 1;
- }
-
- // Raytracing-relevant code starts here
-
- int width = settings.value("Canvas/width").toInt();
- int height = settings.value("Canvas/height").toInt();
-
- // Extracting data pointer from Qt's image API
- QImage image = QImage(width, height, QImage::Format_RGBX8888);
- image.fill(Qt::black);
- RGBA *data = reinterpret_cast<RGBA *>(image.bits());
-
- // Setting up the raytracer
- Config rtConfig{};
- rtConfig.enableShadow = settings.value("Feature/shadows").toBool();
- rtConfig.enableReflection = settings.value("Feature/reflect").toBool();
- rtConfig.enableRefraction = settings.value("Feature/refract").toBool();
- rtConfig.enableTextureMap = settings.value("Feature/texture").toBool();
- rtConfig.enableTextureFilter = settings.value("Feature/texture-filter").toBool();
- rtConfig.enableParallelism = settings.value("Feature/parallel").toBool();
- rtConfig.enableSuperSample = settings.value("Feature/super-sample").toBool();
- rtConfig.enableAntiAliasing = settings.value("Feature/post-process").toBool();
- rtConfig.enableAcceleration = settings.value("Feature/acceleration").toBool();
- rtConfig.enableDepthOfField = settings.value("Feature/depthoffield").toBool();
- rtConfig.maxRecursiveDepth = settings.value("Settings/maximum-recursive-depth").toInt();
- rtConfig.onlyRenderNormals = settings.value("Settings/only-render-normals").toBool();
-
- RayTracer raytracer{ rtConfig };
-
- RayTraceScene rtScene{ width, height, metaData };
-
- // Note that we're passing `data` as a pointer (to its first element)
- // Recall from Lab 1 that you can access its elements like this: `data[i]`
- raytracer.render(data, rtScene);
-
- // Saving the image
- success = image.save(oImagePath);
- if (!success) {
- success = image.save(oImagePath, "PNG");
- }
- if (success) {
- std::cout << "Saved rendered image to \"" << oImagePath.toStdString() << "\"" << std::endl;
- } else {
- std::cerr << "Error: failed to save image to \"" << oImagePath.toStdString() << "\"" << std::endl;
- }
-
- a.exit();
- return 0;
+ // QCoreApplication a(argc, argv);
+
+ // QCommandLineParser parser;
+ // parser.addHelpOption();
+ // parser.addPositionalArgument("config", "Path of the config file.");
+ // parser.process(a);
+
+ // auto positionalArgs = parser.positionalArguments();
+ // if (positionalArgs.size() != 1) {
+ // std::cerr << "Not enough arguments. Please provide a path to a config file (.ini) as a command-line argument." << std::endl;
+ // a.exit(1);
+ // return 1;
+ // }
+
+ // QSettings settings( positionalArgs[0], QSettings::IniFormat );
+ // QString iScenePath = settings.value("IO/scene").toString();
+ // QString oImagePath = settings.value("IO/output").toString();
+
+ // RenderData metaData;
+ // bool success = SceneParser::parse(iScenePath.toStdString(), metaData);
+
+ // if (!success) {
+ // std::cerr << "Error loading scene: \"" << iScenePath.toStdString() << "\"" << std::endl;
+ // a.exit(1);
+ // return 1;
+ // }
+
+ // // Raytracing-relevant code starts here
+
+ // int width = settings.value("Canvas/width").toInt();
+ // int height = settings.value("Canvas/height").toInt();
+
+ // // Extracting data pointer from Qt's image API
+ // QImage image = QImage(width, height, QImage::Format_RGBX8888);
+ // image.fill(Qt::black);
+ // RGBA *data = reinterpret_cast<RGBA *>(image.bits());
+
+ // // Setting up the raytracer
+ // Config rtConfig{};
+ // rtConfig.enableShadow = settings.value("Feature/shadows").toBool();
+ // rtConfig.enableReflection = settings.value("Feature/reflect").toBool();
+ // rtConfig.enableRefraction = settings.value("Feature/refract").toBool();
+ // rtConfig.enableTextureMap = settings.value("Feature/texture").toBool();
+ // rtConfig.enableTextureFilter = settings.value("Feature/texture-filter").toBool();
+ // rtConfig.enableParallelism = settings.value("Feature/parallel").toBool();
+ // rtConfig.enableSuperSample = settings.value("Feature/super-sample").toBool();
+ // rtConfig.enableAntiAliasing = settings.value("Feature/post-process").toBool();
+ // rtConfig.enableAcceleration = settings.value("Feature/acceleration").toBool();
+ // rtConfig.enableDepthOfField = settings.value("Feature/depthoffield").toBool();
+ // rtConfig.maxRecursiveDepth = settings.value("Settings/maximum-recursive-depth").toInt();
+ // rtConfig.onlyRenderNormals = settings.value("Settings/only-render-normals").toBool();
+
+ // RayTracer raytracer{ rtConfig };
+
+ // RayTraceScene rtScene{ width, height, metaData };
+
+ // // Note that we're passing `data` as a pointer (to its first element)
+ // // Recall from Lab 1 that you can access its elements like this: `data[i]`
+ // raytracer.render(data, rtScene);
+
+ // // Saving the image
+ // success = image.save(oImagePath);
+ // if (!success) {
+ // success = image.save(oImagePath, "PNG");
+ // }
+ // if (success) {
+ // std::cout << "Saved rendered image to \"" << oImagePath.toStdString() << "\"" << std::endl;
+ // } else {
+ // std::cerr << "Error: failed to save image to \"" << oImagePath.toStdString() << "\"" << std::endl;
+ // }
+
+ // a.exit();
+ // return 0;
+
+ QApplication a(argc, argv);
+
+ QCoreApplication::setApplicationName("The All Americans 4D Raytracer");
+ QCoreApplication::setOrganizationName("CS 1230/2230");
+ // QCoreApplication::setApplicationVersion(QT_VERSION_STR);
+
+ QSurfaceFormat fmt;
+ fmt.setVersion(4, 1);
+ fmt.setProfile(QSurfaceFormat::CoreProfile);
+ QSurfaceFormat::setDefaultFormat(fmt);
+
+ MainWindow w;
+ w.initialize();
+ w.resize(800, 600);
+ w.show();
+ int return_val = a.exec();
+ w.finish();
+ return return_val;
}
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
new file mode 100644
index 0000000..45c1c2c
--- /dev/null
+++ b/src/mainwindow.cpp
@@ -0,0 +1,384 @@
+#include "mainwindow.h"
+#include "settings.h"
+
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QFileDialog>
+#include <QSettings>
+#include <QLabel>
+#include <QGroupBox>
+#include <iostream>
+
+void MainWindow::initialize() {
+ // create RayTracer
+ rayTracer = new RayTracer(this);
+ imageLabel = new QLabel(this);
+ // aspectRatioWidget = new AspectRatioWidget(this);
+ // aspectRatioWidget->setAspectWidget(imageLabel, 3.f/4.f);
+ QHBoxLayout *hLayout = new QHBoxLayout; // horizontal alignment
+ QVBoxLayout *vLayout = new QVBoxLayout(); // vertical alignment
+ vLayout->setAlignment(Qt::AlignTop);
+ hLayout->addLayout(vLayout);
+ hLayout->addWidget(imageLabel, 1);
+ this->setLayout(hLayout);
+
+ QFont font;
+ font.setPointSize(12);
+ font.setBold(true);
+ QLabel *xy_label = new QLabel(); // XY label
+ xy_label->setText("XY value:");
+ xy_label->setFont(font);
+ QLabel *xz_label = new QLabel(); // XZ label
+ xz_label->setText("XZ value:");
+ xz_label->setFont(font);
+ QLabel *xw_label = new QLabel(); // XW label
+ xw_label->setText("XW value:");
+ xw_label->setFont(font);
+ QLabel *yz_label = new QLabel(); // YZ label
+ yz_label->setText("YZ value:");
+ yz_label->setFont(font);
+ QLabel *yw_label = new QLabel(); // YW label
+ yw_label->setText("YW value:");
+ yw_label->setFont(font);
+ QLabel *zw_label = new QLabel(); // ZW label
+ zw_label->setText("ZW value:");
+ zw_label->setFont(font);
+
+
+ // Create file uploader for scene file
+ uploadFile = new QPushButton();
+ uploadFile->setText(QStringLiteral("Upload Scene File"));
+
+ saveImage = new QPushButton();
+ saveImage->setText(QStringLiteral("Save image"));
+
+ QGroupBox *xyLayout = new QGroupBox(); // horizonal w slider alignment
+ QHBoxLayout *lxy = new QHBoxLayout();
+
+ xySlider = new QSlider(Qt::Orientation::Horizontal); // XY value slider
+ xySlider->setTickInterval(1);
+ xySlider->setMinimum(-1000);
+ xySlider->setMaximum(1000);
+ xySlider->setValue(0);
+
+ xyBox = new QDoubleSpinBox();
+ xyBox->setMinimum(-10.0f);
+ xyBox->setMaximum(10.f);
+ xyBox->setSingleStep(0.1f);
+ xyBox->setValue(0.f);
+
+ lxy->addWidget(xySlider);
+ lxy->addWidget(xyBox);
+ xyLayout->setLayout(lxy);
+
+ // XZ Slider
+ QGroupBox *xzLayout = new QGroupBox(); // horizonal w slider alignment
+ QHBoxLayout *lxz = new QHBoxLayout();
+
+ xzSlider = new QSlider(Qt::Orientation::Horizontal); // XY value slider
+ xzSlider->setTickInterval(1);
+ xzSlider->setMinimum(-1000);
+ xzSlider->setMaximum(1000);
+ xzSlider->setValue(0);
+
+ xzBox = new QDoubleSpinBox();
+ xzBox->setMinimum(-10.0f);
+ xzBox->setMaximum(10.f);
+ xzBox->setSingleStep(0.1f);
+ xzBox->setValue(0.f);
+
+ lxz->addWidget(xzSlider);
+ lxz->addWidget(xzBox);
+ xzLayout->setLayout(lxz);
+
+ // XW Slider
+ QGroupBox *xwLayout = new QGroupBox(); // horizonal w slider alignment
+ QHBoxLayout *lxw = new QHBoxLayout();
+
+ xwSlider = new QSlider(Qt::Orientation::Horizontal); // XY value slider
+ xwSlider->setTickInterval(1);
+ xwSlider->setMinimum(-1000);
+ xwSlider->setMaximum(1000);
+ xwSlider->setValue(0);
+
+ xwBox = new QDoubleSpinBox();
+ xwBox->setMinimum(-10.0f);
+ xwBox->setMaximum(10.f);
+ xwBox->setSingleStep(0.1f);
+ xwBox->setValue(0.f);
+
+ lxw->addWidget(xwSlider);
+ lxw->addWidget(xwBox);
+ xwLayout->setLayout(lxw);
+
+ // YZ Slider
+ QGroupBox *yzLayout = new QGroupBox(); // horizonal w slider alignment
+ QHBoxLayout *lyz = new QHBoxLayout();
+
+ yzSlider = new QSlider(Qt::Orientation::Horizontal); // XY value slider
+ yzSlider->setTickInterval(1);
+ yzSlider->setMinimum(-1000);
+ yzSlider->setMaximum(1000);
+ yzSlider->setValue(0);
+
+ yzBox = new QDoubleSpinBox();
+ yzBox->setMinimum(-10.0f);
+ yzBox->setMaximum(10.f);
+ yzBox->setSingleStep(0.1f);
+ yzBox->setValue(0.f);
+
+ lyz->addWidget(yzSlider);
+ lyz->addWidget(yzBox);
+ yzLayout->setLayout(lyz);
+
+ // YW Slider
+ QGroupBox *ywLayout = new QGroupBox(); // horizonal w slider alignment
+ QHBoxLayout *lyw = new QHBoxLayout();
+
+ ywSlider = new QSlider(Qt::Orientation::Horizontal); // XY value slider
+ ywSlider->setTickInterval(1);
+ ywSlider->setMinimum(-1000);
+ ywSlider->setMaximum(1000);
+ ywSlider->setValue(0);
+
+ ywBox = new QDoubleSpinBox();
+ ywBox->setMinimum(-10.0f);
+ ywBox->setMaximum(10.f);
+ ywBox->setSingleStep(0.1f);
+ ywBox->setValue(100.f);
+
+ lyw->addWidget(ywSlider);
+ lyw->addWidget(ywBox);
+ ywLayout->setLayout(lyw);
+
+ // ZW Slider
+ QGroupBox *zwLayout = new QGroupBox(); // horizonal w slider alignment
+ QHBoxLayout *lzw = new QHBoxLayout();
+
+ zwSlider = new QSlider(Qt::Orientation::Horizontal); // XY value slider
+ zwSlider->setTickInterval(1);
+ zwSlider->setMinimum(-1000);
+ zwSlider->setMaximum(1000);
+ zwSlider->setValue(0);
+
+ zwBox = new QDoubleSpinBox();
+ zwBox->setMinimum(-10.0f);
+ zwBox->setMaximum(10.f);
+ zwBox->setSingleStep(0.1f);
+ zwBox->setValue(100.f);
+
+ lzw->addWidget(zwSlider);
+ lzw->addWidget(zwBox);
+ zwLayout->setLayout(lzw);
+
+ vLayout->addWidget(uploadFile);
+ vLayout->addWidget(saveImage);
+ vLayout->addWidget(xy_label);
+ vLayout->addWidget(xyLayout);
+ vLayout->addWidget(xz_label);
+ vLayout->addWidget(xzLayout);
+ vLayout->addWidget(xw_label);
+ vLayout->addWidget(xwLayout);
+ vLayout->addWidget(yz_label);
+ vLayout->addWidget(yzLayout);
+ vLayout->addWidget(yw_label);
+ vLayout->addWidget(ywLayout);
+ vLayout->addWidget(zw_label);
+ vLayout->addWidget(zwLayout);
+
+ connectUIElements();
+
+ onValChangexyBox(0.0f);
+ onValChangexzBox(0.0f);
+ onValChangexwBox(0.0f);
+ onValChangeyzBox(0.0f);
+ onValChangeywBox(0.0f);
+ onValChangezwBox(0.0f);
+}
+
+void MainWindow::finish() {
+// realtime->finish();
+// delete(realtime);
+}
+
+void MainWindow::connectUIElements() {
+ connectUploadFile();
+ connectSaveImage();
+ connectxy();
+ connectxz();
+ connectxw();
+ connectyz();
+ connectyw();
+ connectzw();
+}
+
+void MainWindow::connectUploadFile() {
+ connect(uploadFile, &QPushButton::clicked, this, &MainWindow::onUploadFile);
+}
+
+void MainWindow::connectSaveImage() {
+ connect(saveImage, &QPushButton::clicked, this, &MainWindow::onSaveImage);
+}
+
+void MainWindow::connectxy() {
+ connect(xySlider, &QSlider::valueChanged, this, &MainWindow::onValChangexySlider);
+ connect(xyBox, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ this, &MainWindow::onValChangexyBox);
+}
+
+void MainWindow::connectxz() {
+ connect(xzSlider, &QSlider::valueChanged, this, &MainWindow::onValChangexzSlider);
+ connect(xzBox, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ this, &MainWindow::onValChangexzBox);
+}
+
+void MainWindow::connectxw() {
+ connect(xwSlider, &QSlider::valueChanged, this, &MainWindow::onValChangexwSlider);
+ connect(xwBox, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ this, &MainWindow::onValChangexwBox);
+}
+
+void MainWindow::connectyz() {
+ connect(yzSlider, &QSlider::valueChanged, this, &MainWindow::onValChangeyzSlider);
+ connect(yzBox, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ this, &MainWindow::onValChangeyzBox);
+}
+
+void MainWindow::connectyw() {
+ connect(ywSlider, &QSlider::valueChanged, this, &MainWindow::onValChangeywSlider);
+ connect(ywBox, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ this, &MainWindow::onValChangeywBox);
+}
+
+void MainWindow::connectzw() {
+ connect(zwSlider, &QSlider::valueChanged, this, &MainWindow::onValChangezwSlider);
+ connect(zwBox, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ this, &MainWindow::onValChangezwBox);
+}
+
+void MainWindow::onUploadFile() {
+ // Get abs path of scene file
+ QString configFilePath = QFileDialog::getOpenFileName(this, tr("Upload File"),
+ QDir::currentPath()
+ .append(QDir::separator())
+ .append("scenefiles")
+ .append(QDir::separator())
+ .append("lights-camera")
+ .append(QDir::separator())
+ .append("required"), tr("Scene Files (*.json)"));
+ if (configFilePath.isNull()) {
+ std::cout << "Failed to load null scenefile." << std::endl;
+ return;
+ }
+
+ settings.sceneFilePath = configFilePath.toStdString();
+
+ std::cout << "Loaded scenefile: \"" << configFilePath.toStdString() << "\"." << std::endl;
+
+ rayTracer->sceneChanged(imageLabel);
+}
+
+void MainWindow::onSaveImage() {
+ if (settings.sceneFilePath.empty()) {
+ std::cout << "No scene file loaded." << std::endl;
+ return;
+ }
+ std::string sceneName = settings.sceneFilePath.substr(0, settings.sceneFilePath.find_last_of("."));
+ sceneName = sceneName.substr(sceneName.find_last_of("/")+1);
+ QString filePath = QFileDialog::getSaveFileName(this, tr("Save Image"),
+ QDir::currentPath()
+ .append(QDir::separator())
+ .append("student_outputs")
+ .append(QDir::separator())
+ .append("lights-camera")
+ .append(QDir::separator())
+ .append("required")
+ .append(QDir::separator())
+ .append(sceneName), tr("Image Files (*.png)"));
+ std::cout << "Saving image to: \"" << filePath.toStdString() << "\"." << std::endl;
+// realtime->saveViewportImage(filePath.toStdString());
+}
+
+void MainWindow::onValChangexySlider(int newValue) {
+ //wSlider->setValue(newValue);
+ xyBox->setValue(newValue/100.f);
+ settings.xy = xyBox->value();
+ rayTracer->settingsChanged(imageLabel);
+}
+
+void MainWindow::onValChangexyBox(double newValue) {
+ xySlider->setValue(int(newValue*100.f));
+ //wBox->setValue(newValue);
+ settings.xy = xyBox->value();
+ rayTracer->settingsChanged(imageLabel);
+}
+
+void MainWindow::onValChangexzSlider(int newValue) {
+ //wSlider->setValue(newValue);
+ xzBox->setValue(newValue/100.f);
+ settings.xz = xzBox->value();
+ rayTracer->settingsChanged(imageLabel);
+}
+
+void MainWindow::onValChangexzBox(double newValue) {
+ xzSlider->setValue(int(newValue*100.f));
+ //wBox->setValue(newValue);
+ settings.xz = xzBox->value();
+ rayTracer->settingsChanged(imageLabel);
+}
+
+void MainWindow::onValChangexwSlider(int newValue) {
+ //wSlider->setValue(newValue);
+ xwBox->setValue(newValue/100.f);
+ settings.xw = xwBox->value();
+ rayTracer->settingsChanged(imageLabel);
+}
+
+void MainWindow::onValChangexwBox(double newValue) {
+ xwSlider->setValue(int(newValue*100.f));
+ //wBox->setValue(newValue);
+ settings.xw = xwBox->value();
+ rayTracer->settingsChanged(imageLabel);
+}
+
+void MainWindow::onValChangeyzSlider(int newValue) {
+ //wSlider->setValue(newValue);
+ yzBox->setValue(newValue/100.f);
+ settings.yz = yzBox->value();
+ rayTracer->settingsChanged(imageLabel);
+}
+
+void MainWindow::onValChangeyzBox(double newValue) {
+ yzSlider->setValue(int(newValue*100.f));
+ //wBox->setValue(newValue);
+ settings.yz = yzBox->value();
+ rayTracer->settingsChanged(imageLabel);
+}
+
+void MainWindow::onValChangeywSlider(int newValue) {
+ //wSlider->setValue(newValue);
+ ywBox->setValue(newValue/100.f);
+ settings.yw = ywBox->value();
+ rayTracer->settingsChanged(imageLabel);
+}
+
+void MainWindow::onValChangeywBox(double newValue) {
+ ywSlider->setValue(int(newValue*100.f));
+ //wBox->setValue(newValue);
+ settings.yw = ywBox->value();
+ rayTracer->settingsChanged(imageLabel);
+}
+
+void MainWindow::onValChangezwSlider(int newValue) {
+ //wSlider->setValue(newValue);
+ zwBox->setValue(newValue/100.f);
+ settings.zw = zwBox->value();
+ rayTracer->settingsChanged(imageLabel);
+}
+
+void MainWindow::onValChangezwBox(double newValue) {
+ zwSlider->setValue(int(newValue*100.f));
+ //wBox->setValue(newValue);
+ settings.zw = zwBox->value();
+ rayTracer->settingsChanged(imageLabel);
+}
diff --git a/src/mainwindow.h b/src/mainwindow.h
new file mode 100644
index 0000000..6c98ae2
--- /dev/null
+++ b/src/mainwindow.h
@@ -0,0 +1,66 @@
+#pragma once
+
+#include <QMainWindow>
+#include <QCheckBox>
+#include <QSlider>
+#include <QSpinBox>
+#include <QDoubleSpinBox>
+#include <QPushButton>
+#include <QLabel>
+// #include "realtime.h"
+#include "raytracer/raytracer.h"
+#include "utils/aspectratiowidget/aspectratiowidget.hpp"
+
+class MainWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ void initialize();
+ void finish();
+ QLabel *imageLabel;
+
+private:
+ void connectUIElements();
+ void connectUploadFile();
+ void connectSaveImage();
+ void connectxy();
+ void connectxz();
+ void connectxw();
+ void connectyz();
+ void connectyw();
+ void connectzw();
+
+ RayTracer *rayTracer;
+ AspectRatioWidget *aspectRatioWidget;
+ QPushButton *uploadFile;
+ QPushButton *saveImage;
+ QSlider *xySlider;
+ QDoubleSpinBox *xyBox;
+ QSlider *xzSlider;
+ QDoubleSpinBox *xzBox;
+ QSlider *xwSlider;
+ QDoubleSpinBox *xwBox;
+ QSlider *yzSlider;
+ QDoubleSpinBox *yzBox;
+ QSlider *ywSlider;
+ QDoubleSpinBox *ywBox;
+ QSlider *zwSlider;
+ QDoubleSpinBox *zwBox;
+
+private slots:
+ void onUploadFile();
+ void onSaveImage();
+ void onValChangexySlider(int newValue);
+ void onValChangexyBox(double newValue);
+ void onValChangexzSlider(int newValue);
+ void onValChangexzBox(double newValue);
+ void onValChangexwSlider(int newValue);
+ void onValChangexwBox(double newValue);
+ void onValChangeyzSlider(int newValue);
+ void onValChangeyzBox(double newValue);
+ void onValChangeywSlider(int newValue);
+ void onValChangeywBox(double newValue);
+ void onValChangezwSlider(int newValue);
+ void onValChangezwBox(double newValue);
+};
diff --git a/src/raytracer/raytracer.cpp b/src/raytracer/raytracer.cpp
index c3466cf..93f5225 100644
--- a/src/raytracer/raytracer.cpp
+++ b/src/raytracer/raytracer.cpp
@@ -3,16 +3,19 @@
#include <iostream>
#include "raytracer.h"
#include "raytracescene.h"
+#include "settings.h"
+#include "mainwindow.h"
//struct Ray {
// glm::vec3 p;
// glm::vec3 d;
//};
-RayTracer::RayTracer(const Config &config) : m_config(config) {}
+// RayTracer::RayTracer(const Config &config) : m_config(config) {}
+RayTracer::RayTracer(QWidget *parent) : QWidget(parent) {}
void RayTracer::render(RGBA *imageData, const RayTraceScene &scene) {
- if(m_config.enableParallelism)
+ if(m_enableParallelism)
{
renderParallel(imageData, scene);
return;
@@ -53,7 +56,7 @@ glm::vec4 RayTracer::getPixelFromRay(
const RayTraceScene &scene,
int depth)
{
- if (depth > m_config.maxRecursiveDepth)
+ if (depth > m_maxRecursiveDepth)
{
return glm::vec4(0.f);
}
@@ -63,7 +66,7 @@ glm::vec4 RayTracer::getPixelFromRay(
glm::vec4 closestIntersectionWorld;
RenderShapeData intersectedShape;
- if (m_config.enableAcceleration)
+ if (m_enableAcceleration)
{
float tWorld = traverseBVH(pWorld, dWorld, intersectedShape, scene.m_bvh);
if (tWorld == FINF)
@@ -147,4 +150,53 @@ glm::vec4 RayTracer::secondaryRays(glm::vec4 pWorld, glm::vec4 dWorld, RayTraceS
}
return illumination / (float) TIMES;
-} \ No newline at end of file
+}
+
+void RayTracer::sceneChanged(QLabel* imageLabel) {
+ // RenderData metaData;
+
+ bool success = SceneParser::parse(settings.sceneFilePath, m_metaData);
+
+ if (!success) {
+ std::cerr << "Error loading scene: \"" << settings.sceneFilePath << "\"" << std::endl;
+ return;
+ }
+
+ int width = 576;
+ int height = 432;
+
+ // render the scene
+ QImage image = QImage(width, height, QImage::Format_RGBX8888);
+ image.fill(Qt::black);
+ RGBA *data = reinterpret_cast<RGBA *>(image.bits());
+
+
+
+ // RayTracer raytracer{ rtConfig };
+
+ RayTraceScene rtScene{ width, height, m_metaData };
+ this->render(data, rtScene);
+
+ QImage flippedImage = image.mirrored(false, false);
+ // make the image larger
+ flippedImage = flippedImage.scaled(2*width, 2*height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ imageLabel->setPixmap(QPixmap::fromImage(flippedImage));
+}
+
+void RayTracer::settingsChanged(QLabel* imageLabel) {
+ int width = 576;
+ int height = 432;
+
+ QImage image = QImage(width, height, QImage::Format_RGBX8888);
+ image.fill(Qt::black);
+ RGBA *data = reinterpret_cast<RGBA *>(image.bits());
+
+ RayTraceScene rtScene{ width, height, m_metaData };
+ this->render(data, rtScene);
+
+ QImage flippedImage = image.mirrored(false, false);
+ flippedImage = flippedImage.scaled(2*width, 2*height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ imageLabel->setPixmap(QPixmap::fromImage(flippedImage));
+}
+
+
diff --git a/src/raytracer/raytracer.h b/src/raytracer/raytracer.h
index 6a16cdf..5fbe907 100644
--- a/src/raytracer/raytracer.h
+++ b/src/raytracer/raytracer.h
@@ -6,6 +6,8 @@
#include "raytracescene.h"
#include "accelerate/kdtree.h"
#include "accelerate/bvh.h"
+#include <QOpenGLWidget>
+#include <QLabel>
// A forward declaration for the RaytraceScene class
@@ -31,12 +33,12 @@ struct Config {
bool onlyRenderNormals = false;
};
-class RayTracer
+class RayTracer : public QWidget
{
public:
// constructor for the config
- explicit RayTracer(const Config &config);
- const Config &m_config;
+ RayTracer(QWidget *parent = nullptr);
+// const Config &m_config;
// Renders the scene synchronously.
// The ray-tracer will render the scene and fill imageData in-place.
@@ -136,5 +138,23 @@ public:
// depth of field
glm::vec4 secondaryRays(glm::vec4 pWorld, glm::vec4 dWorld, RayTraceScene &scene);
+
+ // Old m_config
+
+ bool m_enableShadow = true;
+ bool m_enableReflection = true;
+ bool m_enableRefraction = false;
+ bool m_enableTextureMap = false;
+ bool m_enableAcceleration = true;
+ bool m_enableParallelism = true;
+ int m_maxRecursiveDepth = 4;
+ bool m_enableAntiAliasing = false;
+ bool m_enableDepthOfField = false;
+ bool m_enableSuperSample = false;
+
+ void sceneChanged(QLabel* imageLabel);
+ void settingsChanged(QLabel* imageLabel);
+ RenderData m_metaData;
+
};
diff --git a/src/settings.cpp b/src/settings.cpp
new file mode 100644
index 0000000..3d3e980
--- /dev/null
+++ b/src/settings.cpp
@@ -0,0 +1,3 @@
+#include "settings.h"
+
+Settings settings;
diff --git a/src/settings.h b/src/settings.h
new file mode 100644
index 0000000..ba383b3
--- /dev/null
+++ b/src/settings.h
@@ -0,0 +1,21 @@
+#ifndef SETTINGS_H
+#define SETTINGS_H
+
+#include <string>
+
+struct Settings {
+ std::string sceneFilePath;
+ float xy = 0.f;
+ float z = 0.f;
+ float xz = 0.f;
+ float yz = 0.f;
+ float xw = 0.f;
+ float yw = 0.f;
+ float zw = 0.f;
+};
+
+
+// The global Settings object, will be initialized by MainWindow
+extern Settings settings;
+
+#endif // SETTINGS_H
diff --git a/src/utils/aspectratiowidget/aspectratiowidget.hpp b/src/utils/aspectratiowidget/aspectratiowidget.hpp
new file mode 100644
index 0000000..9a5f81c
--- /dev/null
+++ b/src/utils/aspectratiowidget/aspectratiowidget.hpp
@@ -0,0 +1,66 @@
+#ifndef ASPECTRATIOWIDGET_HPP
+#define ASPECTRATIOWIDGET_HPP
+
+#include <QWidget>
+#include <QBoxLayout>
+
+class AspectRatioWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ AspectRatioWidget(QWidget *parent = 0) : QWidget(parent)
+ {
+ m_layout = new QHBoxLayout();
+ m_layout->setSpacing(0);
+ m_layout->setContentsMargins(0, 0, 0, 0);
+ setLayout(m_layout);
+ }
+
+ // the widget we want to keep the ratio
+ void setAspectWidget(QWidget* widget, const double ratio = 1.0) {
+ m_aspect_widget = widget;
+ m_layout->addWidget(widget);
+ m_ratio = ratio;
+ }
+ void setRatio(const double ratio) {
+ m_ratio = ratio;
+ applyAspectRatio();
+ }
+
+protected:
+ void resizeEvent(QResizeEvent *event) {
+ (void)event;
+ applyAspectRatio();
+ }
+
+public slots:
+ void applyAspectRatio() {
+ int w = this->width();
+ int h = this->height();
+ double aspect = static_cast<double>(h)/static_cast<double>(w);
+
+ if(aspect < m_ratio) // parent is too wide
+ {
+ int target_width = static_cast<int>(static_cast<double>(h)/m_ratio);
+ m_aspect_widget->setMaximumWidth(target_width);
+ m_aspect_widget->setMaximumHeight(h);
+
+ }
+ else // parent is too high
+ {
+ int target_heigth = static_cast<int>(static_cast<double>(w)*m_ratio);
+ m_aspect_widget->setMaximumHeight(target_heigth);
+ m_aspect_widget->setMaximumWidth(w);
+ }
+ }
+
+private:
+ QHBoxLayout* m_layout;
+
+ QWidget* m_aspect_widget;
+
+ double m_ratio;
+};
+
+#endif // ASPECTRATIOWINDOW_H
+
diff --git a/src/utils/sceneparser.cpp b/src/utils/sceneparser.cpp
index 74c605a..99c4f55 100644
--- a/src/utils/sceneparser.cpp
+++ b/src/utils/sceneparser.cpp
@@ -58,7 +58,7 @@ void initTree(SceneNode* currentNode, std::vector<RenderShapeData> *shapes, std:
for(auto primitive : currentNode->primitives) {
- primitive->material.textureData = loadTextureFromFile(QString::fromStdString(primitive->material.textureMap.filename));
+ // primitive->material.textureData = loadTextureFromFile(QString::fromStdString(primitive->material.textureMap.filename));
RenderShapeData rsd = {*primitive, currentCTM, glm::inverse(currentCTM)};
shapes->push_back(rsd);
}