Skip to content
Snippets Groups Projects
Commit 7911546e authored by Yoel's avatar Yoel
Browse files

Added support for TriangleMeshes. Beginning of splitting hierarchy

parent 98ad301e
No related branches found
No related tags found
No related merge requests found
#pragma once
#include "Triangle.h"
namespace shapes {
Triangle::Triangle(util::Vertex p1, util::Vertex p2, util::Vertex p3,
const std::shared_ptr<material::Material>& material)
: p1(p1), p2(p2), p3(p3), material(material) {
recalculateBB();
}
util::AxisAlignedBoundingBox Triangle::bounds() const {
return bb;
}
void Triangle::recalculateBB() {
const util::Vec3 xx = p1.position;
const util::Vec3 yy = p2.position;
const util::Vec3 zz = p3.position;
const util::Vec3 minBound =
util::Vec3(std::min<float>({xx.x(), yy.x(), zz.x()}),
std::min<float>({xx.y(), yy.y(), zz.y()}),
std::min<float>({xx.z(), yy.z(), zz.z()}));
const util::Vec3 maxBound =
util::Vec3(std::max<float>({xx.x(), yy.x(), zz.x()}),
std::max<float>({xx.y(), yy.y(), zz.y()}),
std::max<float>({xx.z(), yy.z(), zz.z()}));
bb = util::AxisAlignedBoundingBox(minBound, maxBound);
}
std::optional<cam::Hit> Triangle::intersect(const cam::Ray& r) const {
util::Vec3 e1 = p2.position - p1.position;
util::Vec3 e2 = p3.position - p1.position;
util::Vec3 pvec = util::cross(r.d, e2);
float det = util::dot(e1, pvec);
if (det < cam::epsilon) return std::nullopt;
util::Vec3 tvec = r.x0 - p1.position;
float u = util::dot(tvec, pvec) / det;
if (u < 0 || u > 1) return std::nullopt;
util::Vec3 qvec = util::cross(tvec, e1);
float v = util::dot(r.d, qvec) / det;
if (v < 0 || u + v > 1) return std::nullopt;
float t = util::dot(e2, qvec) / det;
util::Vec3 hit = r.x0 + r.d * t;
float w = 1 - u - v;
/*
std::cout << p1().normal << std::endl;
std::cout << p2().normal << std::endl;
std::cout << p3().normal << std::endl;
std::cout << u << std::endl;
std::cout << v << std::endl;
std::cout << w << std::endl;*/
// auto bary_normal =
// (u * p1().normal + v * p2().normal + w * p3().normal).normalize();
auto cross_normal =
util::cross(p2.position - p1.position, p3.position - p1.position)
.normalize();
// if (util::dot(bary_normal, cross_normal) < 0)
// std::cout << "Hm" << std::endl;
return std::optional<cam::Hit>(cam::Hit(hit, cross_normal, t, material));
}
} // namespace shapes
#pragma once
#include <memory>
#include <optional>
#include "../camera/Hit.h"
#include "../tools/AxisAlignedBoundingBox.h"
#include "../tools/Vertex.h"
namespace shapes {
class Triangle {
public:
Triangle(util::Vertex p1, util::Vertex p2, util::Vertex p3,
const std::shared_ptr<material::Material>& material);
std::optional<cam::Hit> intersect(const cam::Ray& r) const;
util::AxisAlignedBoundingBox bounds() const;
void recalculateBB();
util::SurfacePoint sampleLight() const;
util::Vec3 calculateLightEmission(const util::SurfacePoint& p,
const util::Vec3& d) const;
const std::shared_ptr<material::Material>& material;
private:
const util::Vertex p1;
const util::Vertex p2;
const util::Vertex p3;
util::AxisAlignedBoundingBox bb;
};
} // namespace shapes
#pragma once
#include "TriangleMesh.h"
#include <sstream>
#include <string>
#include "../tools/ObjectLoader.h"
namespace shapes {
TriangleMesh::TriangleMesh(std::vector<Triangle> triangles)
: triangles(triangles),
material(nullptr),
hierarchy(Group(util::identity())) {
}
TriangleMesh::TriangleMesh(std::istream& in,
const std::shared_ptr<material::Material>& material)
: material(material), hierarchy(Group(util::identity())) {
triangles = util::loadObj(in, material);
}
std::optional<cam::Hit> TriangleMesh::intersect(const cam::Ray& r) const {
std::optional<cam::Hit> result = std::nullopt;
for (auto tri : triangles) {
// if (tri.bounds().intersects(r)) {
std::optional<cam::Hit> temp = tri.intersect(r);
if (temp) {
if (r.in_range(temp->scalar())) {
if (!result) {
result = temp;
} else if (result->scalar() > temp->scalar()) {
result = temp;
}
}
}
//}
}
return result;
}
util::AxisAlignedBoundingBox TriangleMesh::bounds() const {
return util::AxisAlignedBoundingBox(util::Vec3(-2), util::Vec3(2));
}
util::SurfacePoint TriangleMesh::sampleLight() const {
return util::SurfacePoint(util::Vec3(), 0, material);
}
util::Vec3 TriangleMesh::calculateLightEmission(const util::SurfacePoint& p,
const util::Vec3& d) const {
return util::Vec3();
}
util::AxisAlignedBoundingBox TriangleMesh::initBB() {
util::AxisAlignedBoundingBox init = triangles[0].bounds();
for (auto tri : triangles) init + tri.bounds();
return init;
}
} // namespace shapes
#pragma once
#include <vector>
#include "../tools/Vertex.h"
#include "Group.h"
#include "Light.h"
#include "Shape.h"
#include "Triangle.h"
namespace shapes {
class TriangleMesh : public Light, public Shape {
public:
TriangleMesh(std::vector<Triangle> triangles);
TriangleMesh(std::istream& in,
const std::shared_ptr<material::Material>& material);
std::optional<cam::Hit> intersect(const cam::Ray& r) const override;
util::AxisAlignedBoundingBox bounds() const override;
util::SurfacePoint sampleLight() const override;
util::Vec3 calculateLightEmission(const util::SurfacePoint& p,
const util::Vec3& d) const override;
public:
std::shared_ptr<material::Material> material;
std::vector<Triangle> triangles;
private:
Group hierarchy;
util::AxisAlignedBoundingBox initBB();
};
} // namespace shapes
#pragma once
#include "ObjectLoader.h"
#include <sstream>
#include "Vertex.h"
namespace util {
std::vector<shapes::Triangle> loadObj(
std::istream& in, const std::shared_ptr<material::Material>& material) {
std::vector<Vertex> vertices;
std::vector<Vec3> v;
std::vector<Vec3> vt;
std::vector<Vec3> vn;
std::string lineStr;
while (std::getline(in, lineStr)) {
std::istringstream lineSS(lineStr);
std::string lineType;
lineSS >> lineType;
// vertex
if (lineType == "v") {
float x = 0, y = 0, z = 0;
lineSS >> x >> y >> z;
v.push_back(Vec3(x, y, z));
}
// texture
if (lineType == "vt") {
float u = 0, v = 0;
lineSS >> u >> v;
vt.push_back(Vec3(u, v, 0));
}
// normal
if (lineType == "vn") {
float i = 0, j = 0, k = 0;
lineSS >> i >> j >> k;
vn.push_back(Vec3(i, j, k).normalize());
}
// polygon
if (lineType == "f") {
std::string refStr;
while (lineSS >> refStr) {
std::istringstream ref(refStr);
std::string vStr, vtStr, vnStr;
std::getline(ref, vStr, '/');
std::getline(ref, vtStr, '/');
std::getline(ref, vnStr, '/');
int currentv = atoi(vStr.c_str());
int currentvt = atoi(vtStr.c_str());
int currentvn = atoi(vnStr.c_str());
currentv = (currentv >= 0 ? currentv : v.size() + currentv);
currentvt =
(currentvt >= 0 ? currentvt : vt.size() + currentvt);
currentvn =
(currentvn >= 0 ? currentvn : vn.size() + currentvn);
Vertex vert;
vert.position = v[currentv - 1];
vert.texcoord = v[currentvt - 1];
vert.normal = v[currentvn - 1];
vertices.push_back(vert);
}
}
}
std::vector<shapes::Triangle> triangles;
for (int i = 0; i < vertices.size(); i += 3) {
triangles.push_back(
{vertices[i + 0], vertices[i + 1], vertices[i + 2], material});
}
return triangles;
}
} // namespace util
\ No newline at end of file
#pragma once
#include <fstream>
#include <vector>
#include "../shape/Triangle.h"
namespace util {
std::vector<shapes::Triangle> loadObj(
std::istream& in,
const std::shared_ptr<material::Material>& material = nullptr);
} // namespace util
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment