forked from wjakob/nori
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaccel.cpp
114 lines (89 loc) · 3.91 KB
/
accel.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*
This file is part of Nori, a simple educational ray tracer
Copyright (c) 2015 by Wenzel Jakob
Nori is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License Version 3
as published by the Free Software Foundation.
Nori is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <nori/accel.h>
#include <Eigen/Geometry>
NORI_NAMESPACE_BEGIN
void Accel::addMesh(Mesh *mesh) {
if (m_mesh)
throw NoriException("Accel: only a single mesh is supported!");
m_mesh = mesh;
m_bbox = m_mesh->getBoundingBox();
}
void Accel::build() {
/* Nothing to do here for now */
}
bool Accel::rayIntersect(const Ray3f &ray_, Intersection &its, bool shadowRay) const {
bool foundIntersection = false; // Was an intersection found so far?
uint32_t f = (uint32_t) -1; // Triangle index of the closest intersection
Ray3f ray(ray_); /// Make a copy of the ray (we will need to update its '.maxt' value)
/* Brute force search through all triangles */
for (uint32_t idx = 0; idx < m_mesh->getTriangleCount(); ++idx) {
float u, v, t;
if (m_mesh->rayIntersect(idx, ray, u, v, t)) {
/* An intersection was found! Can terminate
immediately if this is a shadow ray query */
if (shadowRay)
return true;
ray.maxt = its.t = t;
its.uv = Point2f(u, v);
its.mesh = m_mesh;
f = idx;
foundIntersection = true;
}
}
if (foundIntersection) {
/* At this point, we now know that there is an intersection,
and we know the triangle index of the closest such intersection.
The following computes a number of additional properties which
characterize the intersection (normals, texture coordinates, etc..)
*/
/* Find the barycentric coordinates */
Vector3f bary;
bary << 1-its.uv.sum(), its.uv;
/* References to all relevant mesh buffers */
const Mesh *mesh = its.mesh;
const MatrixXf &V = mesh->getVertexPositions();
const MatrixXf &N = mesh->getVertexNormals();
const MatrixXf &UV = mesh->getVertexTexCoords();
const MatrixXu &F = mesh->getIndices();
/* Vertex indices of the triangle */
uint32_t idx0 = F(0, f), idx1 = F(1, f), idx2 = F(2, f);
Point3f p0 = V.col(idx0), p1 = V.col(idx1), p2 = V.col(idx2);
/* Compute the intersection positon accurately
using barycentric coordinates */
its.p = bary.x() * p0 + bary.y() * p1 + bary.z() * p2;
/* Compute proper texture coordinates if provided by the mesh */
if (UV.size() > 0)
its.uv = bary.x() * UV.col(idx0) +
bary.y() * UV.col(idx1) +
bary.z() * UV.col(idx2);
/* Compute the geometry frame */
its.geoFrame = Frame((p1-p0).cross(p2-p0).normalized());
if (N.size() > 0) {
/* Compute the shading frame. Note that for simplicity,
the current implementation doesn't attempt to provide
tangents that are continuous across the surface. That
means that this code will need to be modified to be able
use anisotropic BRDFs, which need tangent continuity */
its.shFrame = Frame(
(bary.x() * N.col(idx0) +
bary.y() * N.col(idx1) +
bary.z() * N.col(idx2)).normalized());
} else {
its.shFrame = its.geoFrame;
}
}
return foundIntersection;
}
NORI_NAMESPACE_END