Skip to content

Commit 2a340bf

Browse files
committed
1. Moller-Trumbore: Improve uv indexing and rt test. 2. Version compatablity
1 parent 908be8d commit 2a340bf

5 files changed

Lines changed: 111 additions & 82 deletions

File tree

PathTracing/src/main.cpp

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ ImFont* normalIconFont = 0;
7171
/* ----- GLFW/IMGUI PARAMS ------ */
7272

7373
/* ----- PATHTRACER/PREVIEWER PARAMS ------ */
74-
const std::string version = "2.0.0";
74+
const std::string version = "2.1.0";
75+
const std::string minFileVersion = "2.0.0";
7576

7677
PathTracer pathTracer;
7778
int traceDepth = 3;
@@ -199,6 +200,33 @@ void NewScene()
199200
}
200201
}
201202

203+
int CompareVersions(const std::string& version1, const std::string& version2)
204+
{
205+
std::vector<int> v1;
206+
std::vector<int> v2;
207+
208+
std::string token;
209+
std::istringstream ss1(version1);
210+
while (getline(ss1, token, '.'))
211+
v1.push_back(stoi(token));
212+
213+
std::istringstream ss2(version2);
214+
while (getline(ss2, token, '.'))
215+
v2.push_back(stoi(token));
216+
217+
for (size_t i = 0; i < std::max(v1.size(), v2.size()); ++i)
218+
{
219+
int num1 = (i < v1.size()) ? v1[i] : 0;
220+
int num2 = (i < v2.size()) ? v2[i] : 0;
221+
222+
if (num1 < num2)
223+
return -1;
224+
else if (num1 > num2)
225+
return 1;
226+
}
227+
return 0;
228+
}
229+
202230
void GetResolutionFromSceneFile(const std::string& file)
203231
{
204232
std::ifstream fr(file, std::ofstream::in);
@@ -208,7 +236,7 @@ void GetResolutionFromSceneFile(const std::string& file)
208236
if (line != "Path Tracer Scene File") { fr.close(); return; }
209237
if (!std::getline(fr, line)) { fr.close(); return; }
210238
std::string fileVersion = line.substr(line.find_first_of('=') + 1);
211-
if (fileVersion != version) { fr.close(); return; }
239+
if (CompareVersions(fileVersion, minFileVersion) < 0) { fr.close(); return; }
212240
if (fr.eof()) { fr.close(); return; }
213241

214242
ClearScene();
@@ -239,7 +267,7 @@ void LoadScene(const std::string& file)
239267
if (line != "Path Tracer Scene File") { fr.close(); return; }
240268
if (!std::getline(fr, line)) { fr.close(); return; }
241269
std::string fileVersion = line.substr(line.find_first_of('=') + 1);
242-
if (fileVersion != version) { fr.close(); return; }
270+
if (CompareVersions(fileVersion, minFileVersion) < 0) { fr.close(); return; }
243271
if (fr.eof()) { fr.close(); return; }
244272

245273
ClearScene();
@@ -422,7 +450,7 @@ void LoadObjectPathsFromSceneFile(const std::string& file)
422450
if (line != "Path Tracer Scene File") { fr.close(); return; }
423451
if (!std::getline(fr, line)) { fr.close(); return; }
424452
std::string fileVersion = line.substr(line.find_first_of('=') + 1);
425-
if (fileVersion != version) { fr.close(); return; }
453+
if (CompareVersions(fileVersion, minFileVersion) < 0) { fr.close(); return; }
426454
if (fr.eof()) { fr.close(); return; }
427455

428456
ClearScene();
@@ -1493,7 +1521,7 @@ void GuiRightBar()
14931521
ImGui::Text("Focal Distance");
14941522
ImGui::SameLine(160);
14951523
ImGui::SetNextItemWidth(150);
1496-
if (ImGui::SliderFloat("##focalDist", &fv, 0.f, 5.f, "%.2f",
1524+
if (ImGui::SliderFloat("##focalDist", &fv, 0.1f, 5.f, "%.2f",
14971525
ImGuiSliderFlags_AlwaysClamp))
14981526
{
14991527
previewer.SetCameraFocalDist(fv);

PathTracing/src/mesh.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,6 @@ bool AABB::Intersect(const glm::vec3& ro, const glm::vec3& rd)
6060

6161
void Triangle::Init()
6262
{
63-
// barycentric
64-
barycentricInfo.v0 = v2 - v1;
65-
barycentricInfo.v1 = v3 - v1;
66-
barycentricInfo.d00 = glm::dot(barycentricInfo.v0, barycentricInfo.v0);
67-
barycentricInfo.d01 = glm::dot(barycentricInfo.v0, barycentricInfo.v1);
68-
barycentricInfo.d11 = glm::dot(barycentricInfo.v1, barycentricInfo.v1);
69-
barycentricInfo.invDenom = 1.0f /
70-
(barycentricInfo.d00 * barycentricInfo.d11 -
71-
barycentricInfo.d01 * barycentricInfo.d01);
72-
7363
// TBN
7464
glm::vec3 e1 = v2 - v1;
7565
glm::vec3 e2 = v3 - v1;

PathTracing/src/mesh.h

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
#include "image.h"
1111

12-
const float EPS = 0.001f;
12+
const float EPS = 0.00001f;
1313
const float INF = (float)0xFFFF;
1414

1515
enum class MaterialType
@@ -68,16 +68,6 @@ struct AABB
6868
bool Intersect(const glm::vec3& ro, const glm::vec3& rd);
6969
};
7070

71-
struct TriangleBarycentricInfo
72-
{
73-
glm::vec3 v0;
74-
glm::vec3 v1;
75-
float d00 = 0.0f;
76-
float d01 = 0.0f;
77-
float d11 = 0.0f;
78-
float invDenom = 0.0f;
79-
};
80-
8171
struct Triangle
8272
{
8373
glm::vec3 v1;
@@ -96,8 +86,6 @@ struct Triangle
9686
glm::vec3 tangent;
9787
glm::vec3 bitangent;
9888

99-
TriangleBarycentricInfo barycentricInfo;
100-
10189
bool smoothing = false;
10290

10391
int objectId = -1;

PathTracing/src/pathtracer.cpp

Lines changed: 65 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -370,21 +370,49 @@ const float PathTracer::Rand()
370370
return dis(mRng);
371371
}
372372

373-
const bool PathTracer::IsSameSide(const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& a, const glm::vec3& b) const
373+
const glm::vec3 PathTracer::IntersectTriangle
374+
(
375+
const glm::vec3& ro, const glm::vec3& rd,
376+
const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2
377+
) const
374378
{
375-
glm::vec3 ba = b - a;
376-
glm::vec3 cp1 = glm::cross(ba, (p1 - a));
377-
glm::vec3 cp2 = glm::cross(ba, (p2 - a));
379+
glm::vec3 edge1, edge2, h, s, q;
380+
float a, f, u, v;
378381

379-
return (glm::dot(cp1, cp2) >= 0);
380-
}
382+
edge1 = v1 - v0;
383+
edge2 = v2 - v0;
384+
h = glm::cross(rd, edge2);
385+
a = glm::dot(edge1, h);
381386

382-
const bool PathTracer::IntersectTriangle(const glm::vec3& p, const glm::vec3& a, const glm::vec3& b, const glm::vec3& c) const
383-
{
384-
return (IsSameSide(p, a, b, c) && IsSameSide(p, b, a, c) && IsSameSide(p, c, a, b));
387+
if (abs(a) < EPS)
388+
return glm::vec3(0.f);
389+
390+
f = 1.0f / a;
391+
s = ro - v0;
392+
u = f * glm::dot(s, h);
393+
394+
if (u < 0.0f || u > 1.0f)
395+
return glm::vec3(0.f);
396+
397+
q = glm::cross(s, edge1);
398+
v = f * glm::dot(rd, q);
399+
400+
if (v < 0.0f || u + v > 1.0f)
401+
return glm::vec3(0.f);
402+
403+
float t = f * glm::dot(edge2, q);
404+
405+
if (t > EPS)
406+
return glm::vec3(t, u, v);
407+
408+
return glm::vec3(0.f);
385409
}
386410

387-
const bool PathTracer::Hit(BVHNode* node, const glm::vec3& ro, const glm::vec3& rd, Triangle*& triangleOut, float& distOut)
411+
const bool PathTracer::Hit
412+
(
413+
BVHNode* node, const glm::vec3& ro, const glm::vec3& rd,
414+
Triangle*& triangleOut, float& distOut, glm::vec2& cOut
415+
)
388416
{
389417
if (node->mLeft && node->mRight)
390418
{
@@ -393,32 +421,37 @@ const bool PathTracer::Hit(BVHNode* node, const glm::vec3& ro, const glm::vec3&
393421
Triangle* tLeft = 0;
394422
Triangle* tRight = 0;
395423
float dLeft, dRight;
396-
bool hitLeft = Hit(node->mLeft, ro, rd, tLeft, dLeft);
397-
bool hitRight = Hit(node->mRight, ro, rd, tRight, dRight);
424+
glm::vec2 cLeft, cRight;
425+
bool hitLeft = Hit(node->mLeft, ro, rd, tLeft, dLeft, cLeft);
426+
bool hitRight = Hit(node->mRight, ro, rd, tRight, dRight, cRight);
398427
if (hitLeft && hitRight)
399428
{
400429
if (dLeft < dRight)
401430
{
402431
triangleOut = tLeft;
403432
distOut = dLeft;
433+
cOut = cLeft;
404434
}
405435
else
406436
{
407437
triangleOut = tRight;
408438
distOut = dRight;
439+
cOut = cRight;
409440
}
410441
return true;
411442
}
412443
else if (hitLeft)
413444
{
414445
triangleOut = tLeft;
415446
distOut = dLeft;
447+
cOut = cLeft;
416448
return true;
417449
}
418450
else if (hitRight)
419451
{
420452
triangleOut = tRight;
421453
distOut = dRight;
454+
cOut = cRight;
422455
return true;
423456
}
424457
else
@@ -429,28 +462,24 @@ const bool PathTracer::Hit(BVHNode* node, const glm::vec3& ro, const glm::vec3&
429462
}
430463
else if (node->mTriangle)
431464
{
432-
if (glm::dot(rd, node->mTriangle->normal) == 0.0f)
433-
return false;
434-
distOut = glm::dot((node->mTriangle->v1 - ro), node->mTriangle->normal) / glm::dot(rd, node->mTriangle->normal);
435-
if (distOut < 0)
436-
return false;
437-
// update intersection point
438-
glm::vec3 p = ro + rd * distOut;
439-
440-
if (IntersectTriangle(p, node->mTriangle->v1, node->mTriangle->v2, node->mTriangle->v3))
465+
glm::vec3 test = IntersectTriangle(ro, rd, node->mTriangle->v1, node->mTriangle->v2, node->mTriangle->v3);
466+
if (test.x > 0.f)
441467
{
442468
bool result = true;
443469
// Opacity
444470
if (node->mTriangle->mat->opacityTex)
445471
{
446-
glm::vec2 uv = GetUV(p, node->mTriangle);
472+
glm::vec2 c = glm::vec2(test.y, test.z);
473+
glm::vec2 uv = GetUV(c, node->mTriangle);
447474
float opacity = node->mTriangle->mat->opacityTex->tex2D(uv).r;
448475
result = Rand() < opacity;
449476
}
450477

451478
if (result)
452479
{
453480
triangleOut = node->mTriangle;
481+
distOut = test.x;
482+
cOut = glm::vec2(test.y, test.z);
454483
return true;
455484
}
456485
else
@@ -474,6 +503,8 @@ const glm::vec3 PathTracer::SampleTriangle(const glm::vec3& v0, const glm::vec3&
474503

475504
const glm::vec3 PathTracer::DirectIllumimation(const glm::vec3& rd, const glm::vec3& p, const glm::vec3& n, const glm::vec3& diffuse)
476505
{
506+
if (mLights.size() == 0)
507+
return glm::vec3(0.f);
477508
// sample a light triangle
478509
int lightId = int(floor(Rand() * mLights.size()));
479510
if (lightId == mLights.size() && lightId > 0)
@@ -487,7 +518,8 @@ const glm::vec3 PathTracer::DirectIllumimation(const glm::vec3& rd, const glm::v
487518
return glm::vec3(0.f);
488519
float d = 0.0;
489520
Triangle* t = 0;
490-
if (Hit(mBvh, p, l, t, d))
521+
glm::vec2 c;
522+
if (Hit(mBvh, p, l, t, d, c))
491523
{
492524
if (tLight != t)
493525
return glm::vec3(0.f);
@@ -498,32 +530,14 @@ const glm::vec3 PathTracer::DirectIllumimation(const glm::vec3& rd, const glm::v
498530
return lColor * diffuse * glm::dot(-n, -l);
499531
}
500532

501-
const glm::vec2 PathTracer::GetUV(const glm::vec3& p, Triangle* t) const
533+
const glm::vec2 PathTracer::GetUV(const glm::vec2& c, Triangle* t) const
502534
{
503-
glm::vec3 v2 = p - t->v1;
504-
float d20 = glm::dot(v2, t->barycentricInfo.v0);
505-
float d21 = glm::dot(v2, t->barycentricInfo.v1);
506-
507-
float alpha = (t->barycentricInfo.d11 * d20 - t->barycentricInfo.d01 * d21) *
508-
t->barycentricInfo.invDenom;
509-
float beta = (t->barycentricInfo.d00 * d21 - t->barycentricInfo.d01 * d20) *
510-
t->barycentricInfo.invDenom;
511-
512-
return (1.0f - alpha - beta) * t->uv1 + alpha * t->uv2 + beta * t->uv3;
535+
return (1.0f - c.x - c.y) * t->uv1 + c.x * t->uv2 + c.y * t->uv3;
513536
}
514537

515-
const glm::vec3 PathTracer::GetSmoothNormal(const glm::vec3& p, Triangle* t) const
538+
const glm::vec3 PathTracer::GetSmoothNormal(const glm::vec2& c, Triangle* t) const
516539
{
517-
glm::vec3 v2 = p - t->v1;
518-
float d20 = glm::dot(v2, t->barycentricInfo.v0);
519-
float d21 = glm::dot(v2, t->barycentricInfo.v1);
520-
521-
float alpha = (t->barycentricInfo.d11 * d20 - t->barycentricInfo.d01 * d21) *
522-
t->barycentricInfo.invDenom;
523-
float beta = (t->barycentricInfo.d00 * d21 - t->barycentricInfo.d01 * d20) *
524-
t->barycentricInfo.invDenom;
525-
526-
glm::vec3 n = (1.0f - alpha - beta) * t->n1 + alpha * t->n2 + beta * t->n3;
540+
glm::vec3 n = (1.0f - c.x - c.y) * t->n1 + c.x * t->n2 + c.y * t->n3;
527541
glm::vec3 res = glm::normalize(glm::vec3(n.x, -n.y, n.z));
528542
return glm::normalize(n);
529543
}
@@ -532,14 +546,15 @@ const glm::vec3 PathTracer::Trace(const glm::vec3& ro, const glm::vec3& rd, int
532546
{
533547
float d = 0.0f;
534548
Triangle* t = 0;
535-
if (Hit(mBvh, ro, rd, t, d))
549+
glm::vec2 c;
550+
if (Hit(mBvh, ro, rd, t, d, c))
536551
{
537552
Material& mat = mLoadedObjects[t->objectId].elements[t->elementId].material;
538553
glm::vec3 p = ro + rd * d;
539-
glm::vec2 uv = GetUV(p, t);
554+
glm::vec2 uv = GetUV(c, t);
540555
glm::vec3 n = t->normal;
541556
if (t->smoothing)
542-
n = GetSmoothNormal(p, t);
557+
n = GetSmoothNormal(c, t);
543558
if (mat.normalTex)
544559
{
545560
glm::mat3 TBN = glm::mat3(t->tangent, t->bitangent, n);
@@ -659,7 +674,6 @@ const glm::vec3 PathTracer::Trace(const glm::vec3& ro, const glm::vec3& rd, int
659674
refract = true;
660675
}
661676

662-
iter--;
663677
if (!refract)
664678
{
665679
if (roughness == 1.0f)
@@ -684,6 +698,7 @@ const glm::vec3 PathTracer::Trace(const glm::vec3& ro, const glm::vec3& rd, int
684698
reflectDir = w * cosf(2.0f * M_PI * theta) * u + w * sinf(2.0f * M_PI * theta) * v + sqrtf(1.0f - w * w) * r;
685699
reflectDir = glm::normalize(reflectDir);
686700
}
701+
iter--;
687702
return emiss * mat.emissiveIntensity + Trace(p, reflectDir, depth, iter, inside) * mat.specular;
688703
}
689704
else
@@ -693,6 +708,7 @@ const glm::vec3 PathTracer::Trace(const glm::vec3& ro, const glm::vec3& rd, int
693708
reflectDir = glm::normalize(eta * rd - (eta * glm::dot(n, rd) + sqrtf(k)) * refractN);
694709
p -= n * EPS * 2.0f;
695710
inside = !inside;
711+
iter--;
696712
return emiss * mat.emissiveIntensity + Trace(p, reflectDir, depth, iter, inside) * diffuse;
697713
}
698714
else

PathTracing/src/pathtracer.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,20 @@ class PathTracer
8080

8181
private:
8282
const float Rand();
83-
const bool IsSameSide(const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& a, const glm::vec3& b) const;
84-
const bool IntersectTriangle(const glm::vec3& p, const glm::vec3& a, const glm::vec3& b, const glm::vec3& c) const;
85-
const bool Hit(BVHNode* node, const glm::vec3& ro, const glm::vec3& rd, Triangle*& triangleOut, float& distOut);
83+
const glm::vec3 IntersectTriangle
84+
(
85+
const glm::vec3& ro, const glm::vec3& rd,
86+
const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2
87+
) const;
88+
const bool Hit
89+
(
90+
BVHNode* node, const glm::vec3& ro, const glm::vec3& rd,
91+
Triangle*& triangleOut, float& distOut, glm::vec2& cOut
92+
);
8693
const glm::vec3 SampleTriangle(const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2);
8794
const glm::vec3 DirectIllumimation(const glm::vec3& rd, const glm::vec3& p, const glm::vec3& n, const glm::vec3& diffuse);
88-
const glm::vec2 GetUV(const glm::vec3& p, Triangle* t) const;
89-
const glm::vec3 GetSmoothNormal(const glm::vec3& p, Triangle* t) const;
95+
const glm::vec2 GetUV(const glm::vec2& c, Triangle* t) const;
96+
const glm::vec3 GetSmoothNormal(const glm::vec2& c, Triangle* t) const;
9097
const glm::vec2 SampleCircle();
9198
const glm::vec3 Trace(const glm::vec3& ro, const glm::vec3& rd, int depth = 0, int iter = 0, bool inside = false);
9299

0 commit comments

Comments
 (0)