Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Makeup Assignment #1 #6

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
**Deadline**: 14.12.2020

Please put your name here:
**Name**: .......
**Name**: Shahin Mammadov
## Foreword
### Implementation of a Minimal Ray Tracing System

Expand Down
Binary file added renders/environmentalp4.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added renders/perspective1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added renders/perspective2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added renders/perspective3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 42 additions & 1 deletion src/CameraEnvironmental.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,46 @@
#include "ICamera.h"
#include "ray.h"

// --- IMPLENET class CCameraEnvironmental ---
#define _USE_MATH_DEFINES
#include <math.h>
// --- IMPLEMENT class CCameraEnvironmental ---
// --- PUT YOUR CODE HERE ---

class CCameraEnvironmental : public ICamera
{
public:
CCameraEnvironmental(Size resolution, const Vec3f& pos, float angle)
: ICamera(resolution)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Env camera has no angle

, m_pos(pos)
{
}
virtual ~CCameraEnvironmental(void) = default;

virtual void InitRay(Ray& ray, int x, int y) override
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like your implementation, it general it looks correct. After a closer look, there are some error. You need to spend a bit more time for debugging.

{
// --- PUT YOUR CODE HERE ---
float dx = x;
float dy = y;

auto height = getResolution().height;
auto width = getResolution().width;

double theta = 2 * M_PI * dx / height;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here dx should be decided by width and not height.
The same error for dy.

double phi = acos(1 - 2 * dy / width);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here would be enough to have phi changing from 0 to Pi. arccosine is not needed.

double x1 = sin(phi) * cos(theta);
double y1 = sin(phi) * sin(theta);
double z = cos(phi);
Vec3f spherePoint = Vec3f(x1, y1, z);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this point is on the unit sphere, which is located in the origin. So you can use it as direction vector. Next, you forgot the coordinate system transformation, in the WCS y axis looks up, in the sphere you generate, z axis looks up


ray.org = m_pos;
ray.dir = normalize(spherePoint - m_pos);
ray.t = std::numeric_limits<float>::infinity();

}


private:
// input values
Vec3f m_pos; ///< Camera origin (center of projection)
};

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest the following implementation based on yours:

		float dx = static_cast<float>(x) / getResolution().width;
		float dy = static_cast<float>(y) / getResolution().height;

		float theta = 2 * Pif * dx;
		float phi	 = Pif * dy;
		
		float x1 = sinf(phi) * cosf(theta);
		float z1 = sinf(phi) * sinf(theta);
		float y1 = cosf(phi);

		ray.org = m_pos;
		ray.dir = Vec3f(x1, y1, z1);
		ray.t = std::numeric_limits<float>::infinity();

13 changes: 13 additions & 0 deletions src/CameraPerspective.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,25 @@ class CCameraPerspective : public ICamera
, m_up(up)
{
// --- PUT YOUR CODE HERE ---
m_zAxis = m_dir;
m_xAxis = normalize(m_zAxis.cross(m_up));
m_yAxis = normalize(m_zAxis.cross(m_xAxis));
m_focus = 1.0f / tanf(angle * Pif / 360);
}
virtual ~CCameraPerspective(void) = default;

virtual void InitRay(Ray& ray, int x, int y) override
{
// --- PUT YOUR CODE HERE ---
Size resolution = getResolution();

// Screen-space coordinates in [-1, 1]
float sscx = (2 * static_cast<float>(x) / resolution.width) - 1;
float sscy = (2 * static_cast<float>(y) / resolution.height) - 1;

ray.org = m_pos;
ray.dir = normalize(getAspectRatio() * sscx * m_xAxis + sscy * m_yAxis + m_focus * m_zAxis);
ray.t = std::numeric_limits<float>::infinity();
}


Expand Down
1 change: 1 addition & 0 deletions src/ICamera.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class ICamera
*/
virtual void InitRay(Ray& ray, int x, int y) = 0;


/**
* @brief Retuns the camera resolution in pixels
* @return The camera resolution in pixels
Expand Down
2 changes: 1 addition & 1 deletion src/IPrim.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class IPrim
* @brief Constructor
*/
IPrim(void) = default;
IPrim(const IPrim&) = delete;
IPrim(const IPrim&) = default;
virtual ~IPrim(void) = default;
const IPrim& operator=(const IPrim&) = delete;

Expand Down
40 changes: 39 additions & 1 deletion src/PrimDisc.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,44 @@

#include "IPrim.h"
#include "ray.h"
#include "PrimPlane.h"

// --- IMPLENET class CPrimDisc ---
// --- PUT YOUR CODE HERE ---
// --- PUT YOUR CODE HERE ---

class CPrimDisc : public IPrim {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend to derive the disc from plane primitive here, however the implementation is fine

public:


CPrimDisc(const Vec3f& origin, const Vec3f& normal, double radius)
: IPrim(),
m_origin(origin),
m_normal(normal),
m_radius(radius)
{}

virtual ~CPrimDisc(void) = default;


virtual bool intersect(Ray& ray) const override
{
auto plane = CPrimPlane(m_origin, m_normal);

Ray rayCpy = ray;
if (!plane.intersect(rayCpy))
return false;
auto pt = rayCpy.org + rayCpy.dir * rayCpy.t;
auto d = norm(pt - m_origin);
if (d > m_radius)
return false;
if (rayCpy.t > ray.t)
return false;
ray.t = rayCpy.t;
return true;
}

private:
Vec3f m_origin;
Vec3f m_normal;
double m_radius;
};
17 changes: 16 additions & 1 deletion src/PrimPlane.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,22 @@ class CPrimPlane : public IPrim
virtual bool intersect(Ray& ray) const override
{
// --- PUT YOUR CODE HERE ---
return false;
float num = m_normal.dot(m_origin - ray.org);
float den = m_normal.dot(ray.dir);
if (den == 0)
{
return -1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is a Boolean function, it should be false. This error gives the yellow line on horizon in your renders.

}

float t = num / den;
if (t > ray.t || t < Epsilon)
{
return false;
}

ray.t = t;

return true;
}


Expand Down
30 changes: 29 additions & 1 deletion src/PrimSphere.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,35 @@ class CPrimSphere : public IPrim
virtual bool intersect(Ray &ray) const override
{
// --- PUT YOUR CODE HERE ---
return false;
float a = ray.dir.dot(ray.dir);
float b = 2 * ray.dir.dot(ray.org - m_origin);
float c = (ray.org - m_origin).dot(ray.org - m_origin) - m_radius * m_radius;

// discriminant
float D = b * b - 4 * a * c;
if (D < 0) {
return false;
}

// roots of the equation
float t1;
float t2;

t1 = ((-b) + sqrt(D)) / 2 * a;
t2 = ((-b) - sqrt(D)) / 2 * a;

if ((t1 < Epsilon && t2 < Epsilon) || (t1 > ray.t && t2 > ray.t)) {
return false;
}

if (t1 < t2) {
ray.t = t1;
}
else {
ray.t = t2;
}

return true;
}


Expand Down
20 changes: 19 additions & 1 deletion src/PrimTriangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,25 @@ class CPrimTriangle : public IPrim
virtual bool intersect(Ray& ray) const override
{
// --- PUT YOUR CODE HERE ---
return false;
Vec3f nab = (m_b - ray.org).cross(m_a - ray.org);
Vec3f nbc = (m_c - ray.org).cross(m_b - ray.org);
Vec3f nca = (m_a - ray.org).cross(m_c - ray.org);

float area = nab.dot(ray.dir) + nbc.dot(ray.dir) + nca.dot(ray.dir);
float lambda1 = nab.dot(ray.dir) / area;
float lambda2 = nbc.dot(ray.dir) / area;
float lambda3 = nca.dot(ray.dir) / area;
if (lambda1 < 0 || lambda2 < 0 || lambda3 < 0) {
return false;
}

Vec3f p = m_a * lambda1 + m_b * lambda2 + m_c * lambda3;
float t = p[0] / ray.dir[0];
if (t < Epsilon || t > ray.t) {
return false;
}
ray.t = t;
return true;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

triangles are rendered only in the right part of the screen. I think somewhere inside this algorithm an error. Perhaps in the line float t = p[0] / ray.dir[0];I recommend to check the sign and take into consideration also other dimensions.

}


Expand Down
35 changes: 24 additions & 11 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
#include "PrimSphere.h"
#include "PrimPlane.h"
#include "PrimTriangle.h"
#include "PrimDisc.h"

Mat RenderFrame(ICamera& camera)
{
// scene objects

//CPrimSphere s1(Vec3f(0, 0, 20), 2);
CPrimSphere s1(Vec3f(-2, 1.7f, 0), 2);
CPrimSphere s2(Vec3f(1, -1, 1), 2.2f);
CPrimSphere s3(Vec3f(3, 0.8f, -2), 2);
CPrimPlane p1(Vec3f(0, -1, 0), Vec3f(0, 1, 0));
// Add disc primitive here
//Add disc primitive here

CPrimTriangle t1(Vec3f(-2, 3.7f, 0), Vec3f(1, 2, 1), Vec3f(3, 2.8f, -2));
CPrimTriangle t2(Vec3f(3, 2, 3), Vec3f(3, 2, -3), Vec3f(-3, 2, -3));
Expand All @@ -25,19 +26,29 @@ Mat RenderFrame(ICamera& camera)
for (int x = 0; x < img.cols; x++) {

// Initialize your ray here

// --- PUT YOUR CODE HERE ---

Vec3f col = RGB(0, 0, 0); // background color

camera.InitRay(ray, x, y);
Vec3f col = RGB(0, 0, 0);

/*
* Find closest intersection with scene
* objetcs and calculate color
*/

// --- PUT YOUR CODE HERE ---
if (s1.intersect(ray))
col = RGB(1, 0, 0);// s1
if (s2.intersect(ray))
col = RGB(0, 1, 0); // s2
if (s3.intersect(ray))
col = RGB(0, 0, 1); // s3
if (p1.intersect(ray))
col = RGB(1, 1, 0); // p1
if (t1.intersect(ray))
col = RGB(0, 1, 1); // t1
if (t2.intersect(ray))
col = RGB(1, 1, 1); // t2*/

img.at<Vec3f>(y, x) = col; // store pixel color
img.at<Vec3f>(y, x) = col;
}

img.convertTo(img, CV_8UC3, 255);
Expand All @@ -47,6 +58,7 @@ Mat RenderFrame(ICamera& camera)
int main(int argc, char* argv[])
{
const Size resolution(800, 600);
const Size resolutionE(5120, 2560);
// render three images with different camera settings

CCameraPerspective cam1(resolution, Vec3f(0, 0, 10), Vec3f(0, 0, -1), Vec3f(0, 1, 0), 60);
Expand All @@ -61,9 +73,10 @@ int main(int argc, char* argv[])
Mat img3 = RenderFrame(cam3);
imwrite("perspective3.jpg", img3);

// AddeEnvironmental camera here as cam4
// Mat img4 = RenderFrame(cam4);
// imwrite("orthographic4.jpg", img4);
// Add Environmental camera here as cam4
CCameraEnvironmental cam4(resolutionE, Vec3f(-8, 3, 8), 45);
Mat img4 = RenderFrame(cam4);
imwrite("orthographic4.jpg", img4);

return 0;
}