Materials and emmisive materials

This commit is contained in:
Ben
2019-08-31 15:30:05 +01:00
parent c98371068c
commit 7d72dd95ed
24 changed files with 185 additions and 164 deletions

52
.vscode/settings.json vendored
View File

@@ -1,52 +0,0 @@
{
"files.associations": {
"chrono": "cpp",
"array": "cpp",
"hash_map": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"condition_variable": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"list": "cpp",
"map": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"fstream": "cpp",
"functional": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"memory": "cpp",
"mutex": "cpp",
"new": "cpp",
"optional": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"thread": "cpp",
"type_traits": "cpp",
"tuple": "cpp",
"typeinfo": "cpp",
"utility": "cpp"
}
}

View File

@@ -62,6 +62,7 @@ file(GLOB SourceFiles
${SrcDIR}/engine/*
${SrcDIR}/display/*
${SrcDIR}/definitions/*
${SrcDIR}/definitions/materials/*
${SrcDIR}/definitions/primatives/*
${SrcDIR}/util/*
${SrcDIR}/util/imgui/*

View File

@@ -50,7 +50,7 @@ Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 15
illum 40
newmtl rightWall
Ns 9.803922

View File

@@ -23,6 +23,7 @@ enum OperationMode {
enum RenderMode {
MODE_RENDER_PATHTRACE,
MODE_RENDER_NORMALS,
MODE_RENDER_PATHLENGTH,
MODE_RENDER_DEFAULT
};

View File

@@ -0,0 +1,29 @@
#include "BRDF.hpp"
#include <random>
std::default_random_engine generator;
float rand01() {
std::uniform_real_distribution<float> distribution(0, 1);
return distribution(generator);
}
glm::vec3 CosineBRDF(glm::vec3 normal) {
const float TWO_PI = 2.0f * PI;
float r0 = rand01();
float r1 = rand01();
glm::vec3 uu = glm::normalize(glm::cross(normal, { 0.0f, 1.0f, 1.0f }));
glm::vec3 vv = glm::cross(uu, normal);
float ra = sqrtf(r1);
float rx = ra * cosf(TWO_PI * r0);
float ry = ra * sinf(TWO_PI * r0);
float rz = sqrtf(1.0f - r1);
return glm::normalize(rx * uu + ry * vv + rz * normal);
}

View File

@@ -0,0 +1,3 @@
#include "../../maths.hpp"
glm::vec3 CosineBRDF(glm::vec3 normal);

View File

@@ -0,0 +1,18 @@
#include "material.hpp"
#include "BRDF.hpp"
Material::Material() {
}
Material::Material(glm::vec3 col, float emittance)
: Colour(col),
Emittance(emittance) {
if (Emittance > 0.0f) { Emissive = true; } else { Emissive = false; }
}
glm::vec3 Material::Bounce(glm::vec3 in, glm::vec3 normal) {
return CosineBRDF(normal);
}

View File

@@ -1,24 +1,30 @@
#ifndef INFERNO_DEFINITIONS_MATERIAL_H_
#define INFERNO_DEFINITIONS_MATERIAL_H_
#include "../common.hpp"
#include "../maths.hpp"
#include "../../common.hpp"
#include "../../maths.hpp"
class Texture {};
class Material {
glm::vec3 colour;
Texture Tex;
Texture NormalTexture;
Texture BumpTexture;
Texture GlossTexture;
float BumpMultiplier;
public:
Material();
Material(glm::vec3 col, float emittance = 0.0f);
glm::vec3 Bounce(glm::vec3 in, glm::vec3 normal);
glm::vec3 Colour;
// Texture* Tex;
// Texture* NormalTexture;
// Texture* MetalnessTexture;
// Texture* GlossTexture;
float Emittance;
float Index; // refractive index
float Gloss; // reflection cone angle in radians
float Tint; // specular and refractive tinting
float Reflectivity; // metallic reflection
bool Transparent;
bool Emissive;
};
#endif

View File

@@ -5,8 +5,8 @@
class Plane : public Primative {
public:
Plane(glm::vec3 center, glm::vec3 normal)
: Primative(center, normal) { }
Plane(glm::vec3 center, glm::vec3 normal, Material* mat = nullptr)
: Primative(center, normal, mat) { }
bool Intersect(Ray& ray, float& t) override;
glm::vec3 SurfaceNormal(glm::vec3 hitPoint) override;

View File

@@ -1,6 +1,7 @@
#ifndef INFERNO_DEFINITIONS_PRIMATIVES_PRIMATIVE_H_
#define INFERNO_DEFINITIONS_PRIMATIVES_PRIMATIVE_H_
#include "../materials/material.hpp"
#include "../../maths.hpp"
class Ray;
@@ -24,26 +25,30 @@ public:
glm::vec3 points[3];
glm::vec3 normals[3];
Material* material = nullptr;
PrimativeType type = TYPE_NONE;
// Sphere constructor
Primative(glm::vec3 center, float radius)
Primative(glm::vec3 center, float radius, Material* mat)
: center(center), radius(radius) {
type = TYPE_SPHERE;
material = mat;
}
// Plane constructor
Primative(glm::vec3 center, glm::vec3 normal)
Primative(glm::vec3 center, glm::vec3 normal, Material* mat)
: center(center), normal(normal) {
type = TYPE_PLANE;
material = mat;
}
// Triangle constructor
Primative(glm::vec3 p0, glm::vec3 p1, glm::vec3 p2, glm::vec3 n0, glm::vec3 n1, glm::vec3 n2) {
Primative(glm::vec3 p0, glm::vec3 p1, glm::vec3 p2, glm::vec3 n0, glm::vec3 n1, glm::vec3 n2, Material* mat) {
points[0] = p0; points[1] = p1; points[2] = p2;
normals[0] = n0; normals[1] = n1; normals[2] = n2;
type = TYPE_TRI;
material = mat;
}
virtual bool Intersect(Ray& ray, float& t) = 0;

View File

@@ -5,8 +5,8 @@
class Sphere : public Primative {
public:
Sphere(glm::vec3 center, float radius)
: Primative(center, radius) { }
Sphere(glm::vec3 center, float radius, Material* mat = nullptr)
: Primative(center, radius, mat) { }
bool Intersect(Ray& ray, float& t) override;
glm::vec3 SurfaceNormal(glm::vec3 hitPoint) override;

View File

@@ -5,8 +5,8 @@
class Triangle : public Primative {
public:
Triangle(glm::vec3 p0, glm::vec3 p1, glm::vec3 p2, glm::vec3 n0, glm::vec3 n1, glm::vec3 n2)
: Primative(p0, p1, p2, n0, n1, n2) { }
Triangle(glm::vec3 p0, glm::vec3 p1, glm::vec3 p2, glm::vec3 n0, glm::vec3 n1, glm::vec3 n2, Material* mat = nullptr)
: Primative(p0, p1, p2, n0, n1, n2, mat) { }
bool Intersect(Ray& ray, float& t) override;
glm::vec3 SurfaceNormal(glm::vec3 hitPoint) override;

View File

@@ -8,5 +8,5 @@ Scene::Scene(int width, int height) {
}
glm::vec3 Scene::SampleSky(Ray ray) {
return { 10.0f, 10.0f, 10.0f };
return { 0.0f, 0.0f, 0.0f };
}

View File

@@ -17,7 +17,7 @@ void FrameBuffer::SetPixel(int x, int y, uint32_t p) {
}
void FrameBuffer::SetPixel(int x, int y, glm::vec3 p) {
Pixel pixel{ (uint8_t)(p.r * 255.0f), (uint8_t)(p.g * 255.0f), (uint8_t)(p.b * 255.0f) };
Pixel pixel{ (uint8_t)(pow(p.r, Gamma) * 255.0f), (uint8_t)(pow(p.g, Gamma) * 255.0f), (uint8_t)(pow(p.b, Gamma) * 255.0f) };
Data[y * this->XRes + x] = pixel.rgb();
}
@@ -35,7 +35,7 @@ void FrameBuffer::SetPixelSafe(int x, int y, uint32_t p) {
void FrameBuffer::SetPixelSafe(int x, int y, glm::vec3 p) {
if (x >= 0 && x < this->XRes && y >= 0 && this->YRes) {
Pixel pixel{ (uint8_t)(p.r * 255.0f), (uint8_t)(p.g * 255.0f), (uint8_t)(p.b * 255.0f) };
Pixel pixel{ (uint8_t)(pow(p.r, Gamma) * 255.0f), (uint8_t)(pow(p.g, Gamma) * 255.0f), (uint8_t)(pow(p.b, Gamma) * 255.0f) };
Data[y * this->XRes + x] = pixel.rgb();
}
}

View File

@@ -23,6 +23,8 @@ public:
void ClearFramebuffer();
uint32_t* Data;
int XRes, YRes;
float Gamma = 1.0f / 2.3f;
~FrameBuffer();
};

View File

@@ -34,6 +34,15 @@ void ToneMapFrameBuffer::AddPixelSafe(int x, int y, glm::vec3 p) {
}
}
void ToneMapFrameBuffer::AddPixelSafeDepth(int x, int y, glm::vec3 p) {
if (x >= 0 && x < this->XRes && y >= 0 && this->YRes) {
if (LastOp != OPERATION_ADD_DEPTH) { ClearFramebuffer(); }
LastOp = OPERATION_ADD_DEPTH;
RenderTo[y * this->XRes + x] += p;
}
}
void ToneMapFrameBuffer::SetFramebuffer(glm::vec3* fb) {
free(ProcData);
RenderTo = fb;

View File

@@ -10,9 +10,10 @@ class FrameBuffer;
class Pixel;
enum LastOperation {
OPERATION_NONE,
OPERATION_SET,
OPERATION_ADD
OPERATION_ADD,
OPERATION_ADD_DEPTH,
OPERATION_NONE
};
class ToneMapFrameBuffer {
@@ -20,8 +21,9 @@ public:
ToneMapFrameBuffer(int xres, int yres);
void SetPixel(int x, int y, glm::vec3 p);
void SetPixelSafe(int x, int y, glm::vec3);
void AddPixelSafe(int x, int y, glm::vec3);
void SetPixelSafe(int x, int y, glm::vec3 p);
void AddPixelSafe(int x, int y, glm::vec3 p);
void AddPixelSafeDepth(int x, int y, glm::vec3 p);
void SetFramebuffer(glm::vec3* fb);
void ClearFramebuffer();

View File

@@ -51,10 +51,14 @@ void ProgressiveRenderer::Input() {
ImGui::NewFrame();
ImGui::Begin("Debug");
if (m_engine->Mode != MODE_RENDER_NORMALS) {
if (m_engine->Mode != MODE_RENDER_NORMALS && m_engine->Mode != MODE_RENDER_PATHLENGTH) {
std::stringstream str; str << "SPP: " << m_engine->SPP;
ImGui::Text(str.str().c_str());
}
else if (m_engine->Mode == MODE_RENDER_PATHLENGTH) {
std::stringstream str; str << "Depth SPP: " << m_engine->SPPDepth;
ImGui::Text(str.str().c_str());
}
std::stringstream str0; str0 << "FPS: " << 1.0f / AverageFrameTime;
ImGui::Text(str0.str().c_str());
std::stringstream str1; str1 << "MS Per Frame: " << AverageFrameTime * 1000.0f;
@@ -71,13 +75,16 @@ void ProgressiveRenderer::Input() {
ImGui::BeginChild("Render Settings");
const char* renderItems[] = { "PathTrace", "Normals" };
const char* renderItems[] = { "PathTrace", "Normals", "Path Length" };
ImGui::Combo("Render Mode", &m_renderModeSelected, renderItems, IM_ARRAYSIZE(renderItems));
m_engine->Mode = (RenderMode)m_renderModeSelected;
const char* toneMapItems[] = { "Clamp", "Basic Tonemap" };
ImGui::Combo("ToneMap Mode", &m_toneMapModeSelected, toneMapItems, IM_ARRAYSIZE(toneMapItems));
ImGui::SliderFloat("Gamma", &m_gamma, 1.0f, 3.0f);
m_interface->Framebuffer->Gamma = 1.0f / m_gamma;
ImGui::EndChild();
ImGui::End();
}

View File

@@ -44,6 +44,8 @@ private:
int m_toneMapModeSelected = 1;
int m_framesRendererd = 0;
float m_gamma = 2.3f;
};
#endif

View File

@@ -1,7 +1,5 @@
#include "renderengine.hpp"
#include <random>
#include "../pixel.hpp"
#include "../util/threadpool.hpp"
@@ -34,12 +32,15 @@ void workerThread(RenderThreadPool* threadpool, ProgressiveRenderer* renderer, i
for (int y = yStart; y < yStart + yRange; y++)
for (int x = 0; x < renderer->m_scene->w; x++) {
Ray ray = renderer->m_scene->camera->CastRay(x, y);
glm::vec3 col = renderer->m_engine->GetColour(ray, 0);
int depth = 0;
glm::vec3 col = renderer->m_engine->GetColour(ray, depth);
if (renderer->m_engine->Mode == MODE_RENDER_NORMALS) {
threadpool->MappedThreadFrameBuffer->SetPixelSafe(x, y, col);
} else if (renderer->m_engine->Mode == MODE_RENDER_PATHLENGTH) {
col.r = depth; col.g = depth / 3.0f; col.b = depth / 3.0f;
threadpool->MappedThreadFrameBuffer->AddPixelSafeDepth(x, y, col);
} else {
// threadpool->MappedThreadFrameBuffer->SetPixelSafe(x, y, col);
threadpool->MappedThreadFrameBuffer->AddPixelSafe(x, y, col);
}
}
@@ -61,36 +62,8 @@ void RenderEngine::SetScene(Scene* scene) {
m_scene = scene;
}
std::default_random_engine generator;
// std::uniform_real_distribution<float> distribution(-1,1);
// (float)rand() / float(RAND_MAX)*2.0f - 1.0f;
float rand01() {
std::uniform_real_distribution<float> distribution(0, 1);
return distribution(generator);
}
glm::vec3 CosineBRDF(glm::vec3 normal) {
const float TWO_PI = 2.0f * PI;
float r0 = rand01();
float r1 = rand01();
glm::vec3 uu = glm::normalize(glm::cross(normal, { 0.0f, 1.0f, 1.0f }));
glm::vec3 vv = glm::cross(uu, normal);
float ra = sqrtf(r1);
float rx = ra * cosf(TWO_PI * r0);
float ry = ra * sinf(TWO_PI * r0);
float rz = sqrtf(1.0f - r1);
return glm::normalize(rx * uu + ry * vv + rz * normal);
}
glm::vec3 RenderEngine::GetColour(Ray ray, int depth) {
if (depth > 6) return { 0.0f, 0.0f, 0.0f };
glm::vec3 RenderEngine::GetColour(Ray ray, int& depth) {
if (depth > 5) return { 0.0f, 0.0f, 0.0f };
float t; Primative* hit = nullptr;
bool didhit = TraceRayScene(ray, m_scene, t, hit);
@@ -100,21 +73,20 @@ glm::vec3 RenderEngine::GetColour(Ray ray, int depth) {
glm::vec3 normal = hit->SurfaceNormal(hitPoint);
if (Mode == MODE_RENDER_NORMALS) { return GetNormalColour(normal); }
std::uniform_real_distribution<float> distribution(0, 2);
int col = round(distribution(generator));
glm::vec3 colour = hit->material->Colour;
glm::vec3 colour = { 1.0f, 1.0f, 1.0f };
if (hit->type == TYPE_PLANE) {
glm::vec2 uv = hit->TexCoords(hitPoint);
float angle = fastDegreetoRadian(.0f);
float s = uv.x * cos(angle) - uv.y * sin(angle);
float t = uv.y * cos(angle) + uv.x * sin(angle);
float S = 0.05f; float T = 0.05f;
float pattern = (modulo(s * S) < 0.5f) ^ (modulo(t * T) < 0.5f);
colour.r = pattern; colour.g = pattern; colour.b = pattern;
}
if (hit->material->Emissive) return (colour * hit->material->Emittance);
//if (hit->type == TYPE_PLANE) {
// glm::vec2 uv = hit->TexCoords(hitPoint);
// float angle = fastDegreetoRadian(.0f);
// float s = uv.x * cos(angle) - uv.y * sin(angle);
// float t = uv.y * cos(angle) + uv.x * sin(angle);
// float S = 0.05f; float T = 0.05f;
// float pattern = (modulo(s * S) < 0.5f) ^ (modulo(t * T) < 0.5f);
// colour.r = pattern; colour.g = pattern; colour.b = pattern;
//}
glm::vec3 direction = CosineBRDF(normal);
glm::vec3 direction = hit->material->Bounce(ray.direction, normal);
Ray newRay{ hitPoint, direction };
@@ -126,19 +98,30 @@ glm::vec3 RenderEngine::GetColour(Ray ray, int depth) {
newRay.origin = ray.origin + ray.direction * t + normal * EPSILON;
}
return GetColour(newRay, depth + 1) * colour;
depth++;
return GetColour(newRay, depth) * colour;
}
void RenderEngine::PostProcess(glm::vec3* src, glm::vec3* dst, int w, int h) {
if (Mode == MODE_RENDER_NORMALS) {
SPP = 0;
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++) {
dst[y * w + x] = src[y * w + x];
}
SPP = 0;
return;
}
if (Mode == MODE_RENDER_PATHLENGTH) {
SPP = 0;
SPPDepth++;
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++) {
dst[y * w + x] = src[y * w + x] / (float)SPPDepth;
}
return;
}
SPP++;
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++) {

View File

@@ -13,15 +13,17 @@ public:
RenderEngine();
void SetScene(Scene* scene);
glm::vec3 GetColour(Ray ray, int depth);
glm::vec3 GetColour(Ray ray, int& depth);
void PostProcess(glm::vec3* src, glm::vec3* dst, int w, int h);
RenderMode Mode = MODE_RENDER_PATHTRACE;
RenderMode Mode = MODE_RENDER_DEFAULT;
int SPP = 0;
int SPPDepth = 0;
private:
glm::vec3 GetNormalColour(glm::vec3 normal);
Scene* m_scene = nullptr;

View File

@@ -3,6 +3,8 @@
#define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cpp
#include "tiny_obj_loader.hpp"
#include "../definitions/materials/material.hpp"
#include "../definitions/primatives/primative.hpp"
#include "../definitions/primatives/triangle.hpp"
#include "../maths.hpp"
@@ -19,14 +21,14 @@ glm::vec3 getNormal(glm::vec3 p0, glm::vec3 p1, glm::vec3 p2) {
return normal;
}
std::vector<Triangle*> LoadTrianglesBasic(std::string path) {
std::vector<Triangle*> LoadTrianglesBasic(std::string path, std::string basePath) {
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials;
std::string warn, err;
bool canLoad = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, path.c_str());
bool canLoad = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, path.c_str(), basePath.c_str());
if (!err.empty() || !canLoad) {
std::cerr << "Cannot load obj: '" << path << "': " << err << std::endl;
@@ -43,28 +45,30 @@ std::vector<Triangle*> LoadTrianglesBasic(std::string path) {
size_t index_offset = 0;
for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) {
int fv = shapes[s].mesh.num_face_vertices[f];
if (fv == 3) {
tinyobj::real_t avx[3];
tinyobj::real_t avy[3];
tinyobj::real_t avz[3];
if (fv == 3) {
tinyobj::real_t avx[3];
tinyobj::real_t avy[3];
tinyobj::real_t avz[3];
tinyobj::real_t anx[3];
tinyobj::real_t any[3];
tinyobj::real_t anz[3];
tinyobj::real_t anx[3];
tinyobj::real_t any[3];
tinyobj::real_t anz[3];
for (size_t v = 0; v < fv; v++) {
tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v];
for (size_t v = 0; v < fv; v++) {
tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v];
avx[v] = attrib.vertices[3 * idx.vertex_index + 0];
avy[v] = attrib.vertices[3 * idx.vertex_index + 1];
avz[v] = attrib.vertices[3 * idx.vertex_index + 2];
avx[v] = attrib.vertices[3 * idx.vertex_index + 0];
avy[v] = attrib.vertices[3 * idx.vertex_index + 1];
avz[v] = attrib.vertices[3 * idx.vertex_index + 2];
anx[v] = attrib.normals[3 * idx.normal_index + 0];
any[v] = attrib.normals[3 * idx.normal_index + 1];
anz[v] = attrib.normals[3 * idx.normal_index + 2];
}
anx[v] = attrib.normals[3 * idx.normal_index + 0];
any[v] = attrib.normals[3 * idx.normal_index + 1];
anz[v] = attrib.normals[3 * idx.normal_index + 2];
}
// tinyobj::material_t material = materials[shapes[s].mesh.material_ids[f]];
tinyobj::material_t material = materials[shapes[s].mesh.material_ids[f]];
Material* mat = new Material({ material.diffuse[0], material.diffuse[1], material.diffuse[2] }, material.illum);
// glm::vec3 normal = getNormal(
// {avx[0], avy[0], avz[0]},
@@ -82,6 +86,8 @@ std::vector<Triangle*> LoadTrianglesBasic(std::string path) {
{anx[0], any[0], anz[0]},
{anx[1], any[1], anz[1]},
{anx[2], any[2], anz[2]},
mat,
};
triangles.push_back(tmp);

View File

@@ -8,6 +8,6 @@
class Triangle;
std::vector<Triangle*> LoadTrianglesBasic(std::string path);
std::vector<Triangle*> LoadTrianglesBasic(std::string path, std::string basePath = "");
#endif

View File

@@ -2,8 +2,8 @@
#include "../src/inferno.hpp"
static const int width = 600;
static const int height = 600;
static const int width = 1000;
static const int height = 1000;
int main(int argc, char** argv) {
InfernoEngine inferno;
@@ -18,25 +18,22 @@ int main(int argc, char** argv) {
Scene* scene = new Scene(width, height);
scene->camera = new Camera(width, height);
//scene->objects.push_back(new Sphere({ 0.0f, 0.0f, -8.0f }, 1.0f));
//scene->objects.push_back(new Sphere({ 0.0f, 0.0f, -4.0f }, 1.0f));
//scene->objects.push_back(new Sphere({ 2.0f, 0.0f, -8.0f }, 1.0f));
//scene->objects.push_back(new Sphere({ -2.0f, 0.0f, -8.0f }, 1.0f));
//scene->objects.push_back(new Plane( { 0.0f, -25.0f, 0.0f }, { 0.0f, -1.0f, 1.0f }));
//scene->objects.push_back(new Plane( { 0.0f, -25.0f, 0.0f }, { 0.0f, -1.0f, 0.0f }));
// std::vector<Triangle*> tris = LoadTrianglesBasic("/home/ben/programming/inferno/resources/dragon-normals.obj");
//std::vector<Triangle*> tris = LoadTrianglesBasic("E:/Projects/Inferno/resources/dragon-normals.obj");
//std::vector<Triangle*> tris = LoadTrianglesBasic("E://Projects//Inferno//resources//dragon-normals.obj", "E://Projects//Inferno//resources");
//for (const auto& object : tris)
// object->Translate({ 0.0f, -5.0f, -20.0f });
// std::vector<Triangle*> tris = LoadTrianglesBasic("/home/ben/programming/inferno/resources/lucy-normals.obj");
std::vector<Triangle*> tris = LoadTrianglesBasic("E:/Projects/Inferno/resources/lucy-normals.obj");
for (const auto& object : tris)
object->Translate({ 0.0f, -3.9f, -10.6f });
//std::vector<Triangle*> tris = LoadTrianglesBasic("/home/ben/programming/inferno/resources/cornell.obj");
//std::vector<Triangle*> tris = LoadTrianglesBasic("E:/Projects/Inferno/resources/cornell.obj");
//std::vector<Triangle*> tris = LoadTrianglesBasic("E://Projects//Inferno//resources//lucy-normals.obj", "E://Projects//Inferno//resources");
//for (const auto& object : tris)
// object->Translate({ 0.0f, -0.9f, -3.0f });
// object->Translate({ 0.0f, -3.9f, -10.6f });
std::vector<Triangle*> tris = LoadTrianglesBasic("E://Projects//Inferno//resources//cornell.obj", "E://Projects//Inferno//resources");
for (const auto& object : tris)
object->Translate({ 0.0f, -0.9f, -3.0f });
Mesh* mesh = new Mesh(tris);
mesh->Optimise();