diff --git a/openVulkanoCpp/Scene/Geometry.cpp b/openVulkanoCpp/Scene/Geometry.cpp index 080bd51..a05f0b2 100644 --- a/openVulkanoCpp/Scene/Geometry.cpp +++ b/openVulkanoCpp/Scene/Geometry.cpp @@ -91,35 +91,7 @@ namespace OpenVulkano::Scene } for (int i = 0; i < vertexCount; i++) { - float x = vertices[i].position.x; - float y = vertices[i].position.y; - float z = vertices[i].position.z; - - if (x < aabb.min.x) - { - aabb.min.x = x; - } - if (y < aabb.min.y) - { - aabb.min.y = y; - } - if (z < aabb.min.z) - { - aabb.min.z = z; - } - - if (x > aabb.max.x) - { - aabb.max.x = x; - } - if (y > aabb.max.y) - { - aabb.max.y = y; - } - if (z > aabb.max.z) - { - aabb.max.z = z; - } + aabb.Grow(vertices[i].position); } } diff --git a/openVulkanoCpp/Scene/Ray.cpp b/openVulkanoCpp/Scene/Ray.cpp index 155ab74..c082328 100644 --- a/openVulkanoCpp/Scene/Ray.cpp +++ b/openVulkanoCpp/Scene/Ray.cpp @@ -51,17 +51,31 @@ namespace OpenVulkano::Scene const Math::Vector3f& v2) const { RayHit hitRes; - vec2 baryPos; - if (intersectRayTriangle(m_origin, m_dir, v0, v1, v2, baryPos, hitRes.distance) && hitRes.distance >= 0) + if (intersectRayTriangle(m_origin, m_dir, v0, v1, v2, m_baryPos, hitRes.distance) && hitRes.distance >= 0) { - hitRes.point = (1.f - baryPos.x - baryPos.y) * v0 + baryPos.x * v1 + baryPos.y * v2; - // calculate like cross product or leave empty ? what if current triangle is smoothly shaded ? - hitRes.normal = Math::Vector3f(0); + hitRes.point = (1.f - m_baryPos.x - m_baryPos.y) * v0 + m_baryPos.x * v1 + m_baryPos.y * v2; + Math::Vector3f e = v1 - v0; + Math::Vector3f e2 = v2 - v0; + // triangle normal. won't work if triangle is smoothly shaded. use other overloaded method instead. + hitRes.normal = normalize(cross(e, e2)); return hitRes; } return {}; } + std::optional Ray::IntersectTriangle(const Math::Vector3f& v0, const Math::Vector3f& v1, + const Math::Vector3f& v2, const Math::Vector3f& n0, + const Math::Vector3f& n1, const Math::Vector3f& n2) const + { + auto hit = IntersectTriangle(v0, v1, v2); + if (hit && (n0 != n1 || n0 != n2 || n1 != n2)) + { + // TODO: NEED ACTUAL TESTING + hit->normal = normalize((1.f - m_baryPos.x - m_baryPos.y) * n0 + m_baryPos.x * n1 + m_baryPos.y * n2); + } + return hit; + } + std::optional Ray::IntersectQuad(const Math::Vector3f& v0, const Math::Vector3f& v1, const Math::Vector3f& v2, const Math::Vector3f& v3) const { @@ -92,71 +106,69 @@ namespace OpenVulkano::Scene int Ray::IntersectAABB(const Math::AABB& bbox, RayHit& p1, RayHit& p2) const { - const auto bMax = bbox.max; - const auto bMin = bbox.min; + const auto tmin = (bbox.min - m_origin) / m_dir; + const auto tmax = (bbox.max - m_origin) / m_dir; + float txmin = tmin.x; + float txmax = tmax.x; + float tymin = tmin.y; + float tymax = tmax.y; + float tzmin = tmin.z; + float tzmax = tmax.z; - float tmin = (bMin.x - m_origin.x) / m_dir.x; - float tmax = (bMax.x - m_origin.x) / m_dir.x; - if (tmin > tmax) + if (txmin > txmax) { - std::swap(tmin, tmax); + std::swap(txmin, txmax); } - - float tymin = (bMin.y - m_origin.y) / m_dir.y; - float tymax = (bMax.y - m_origin.y) / m_dir.y; if (tymin > tymax) { std::swap(tymin, tymax); } - - if ((tmin > tymax) || (tymin > tmax)) + if ((txmin > tymax) || (tymin > txmax)) { return 0; } - if (tymin > tmin) + if (tymin > txmin) { - tmin = tymin; + txmin = tymin; } - if (tymax < tmax) + if (tymax < txmax) { - tmax = tymax; + txmax = tymax; } - float tzmin = (bMin.z - m_origin.z) / m_dir.z; - float tzmax = (bMax.z - m_origin.z) / m_dir.z; if (tzmin > tzmax) { std::swap(tzmin, tzmax); } - if ((tmin > tzmax) || (tzmin > tmax)) + if ((txmin > tzmax) || (tzmin > txmax)) { return 0; } - if (tzmin > tmin) + if (tzmin > txmin) { - tmin = tzmin; + txmin = tzmin; } - if (tzmax < tmax) + if (tzmax < txmax) { - tmax = tzmax; + txmax = tzmax; } int intersections = 2; - if (tmin < 0) + if (txmin < 0) { - if (tmax < 0) + if (txmax < 0) { return 0; } intersections--; - tmin = tmax; + txmin = txmax; } - p1.point = m_origin + tmin * m_dir; - p2.point = m_origin + tmax * m_dir; + p1.point = m_origin + txmin * m_dir; + p2.point = m_origin + txmax * m_dir; p1.distance = distance(m_origin, p1.point); p2.distance = distance(m_origin, p2.point); p1.normal = p2.normal = Math::Vector3f(0); @@ -179,9 +191,9 @@ namespace OpenVulkano::Scene int Ray::IntersectSphere(const Math::Vector3f& center, float radius, RayHit& p1, RayHit& p2) const { const Math::Vector3f L = m_origin - center; - const float a = dot(m_dir, m_dir); // equals to length^2 + const float a = length2(m_dir); const float b = 2 * dot(m_dir, L); - const float c = dot(L, L) - radius * radius; + const float c = length2(L) - radius * radius; float x1, x2; int roots = ::SolveQuadraticEquation(a, b, c, x1, x2); diff --git a/openVulkanoCpp/Scene/Ray.hpp b/openVulkanoCpp/Scene/Ray.hpp index 889b945..080766c 100644 --- a/openVulkanoCpp/Scene/Ray.hpp +++ b/openVulkanoCpp/Scene/Ray.hpp @@ -18,32 +18,33 @@ namespace OpenVulkano::Scene Math::Vector3f point; Math::Vector3f normal; float distance; - bool operator==(const RayHit& other) const - { - return point == other.point && normal == other.normal && distance == other.distance; - } - bool operator!=(const RayHit& other) const { return !((*this) == other); } + bool operator==(const RayHit& other) const = default; + bool operator!=(const RayHit& other) const = default; }; class Ray { public: - Ray() : m_origin(0), m_dir(0) {} + Ray() = default; Ray(const Math::Vector3f& origin, const Math::Vector3f& dir) : m_origin(origin), m_dir(Math::Utils::normalize(dir)) { } void SetPosition(const Math::Vector3f& origin) { m_origin = origin; } void SetDir(const Math::Vector3f& dir) { m_dir = dir; } - std::optional IntersectSphere(const Math::Vector3f& center, float radius) const; + [[nodiscard]] std::optional IntersectSphere(const Math::Vector3f& center, float radius) const; int IntersectSphere(const Math::Vector3f& center, float radius, RayHit& p1, RayHit& p2) const; - std::optional IntersectTriangle(const Math::Vector3f& v0, const Math::Vector3f& v1, + [[nodiscard]] std::optional IntersectTriangle(const Math::Vector3f& v0, const Math::Vector3f& v1, const Math::Vector3f& v2) const; - std::optional IntersectQuad(const Math::Vector3f& v0, const Math::Vector3f& v1, + [[nodiscard]] std::optional IntersectTriangle(const Math::Vector3f& v0, const Math::Vector3f& v1, + const Math::Vector3f& v2, const Math::Vector3f& n0, + const Math::Vector3f& n1, const Math::Vector3f& n2) const; + [[nodiscard]] std::optional IntersectQuad(const Math::Vector3f& v0, const Math::Vector3f& v1, const Math::Vector3f& v2, const Math::Vector3f& v3) const; - std::optional IntersectAABB(const Math::AABB& bbox) const; + [[nodiscard]] std::optional IntersectAABB(const Math::AABB& bbox) const; int IntersectAABB(const Math::AABB& bbox, RayHit& p1, RayHit& p2) const; - std::optional IntersectPlane(const Math::Vector3f& pOrigin, const Math::Vector3f& pNorm) const; + [[nodiscard]] std::optional IntersectPlane(const Math::Vector3f& pOrigin, + const Math::Vector3f& pNorm) const; [[nodiscard]] Math::Vector3f& GetOrigin() { return m_origin; } [[nodiscard]] Math::Vector3f& GetDir() { return m_dir; } [[nodiscard]] const Math::Vector3f& GetOrigin() const { return m_origin; } @@ -51,5 +52,6 @@ namespace OpenVulkano::Scene private: Math::Vector3f m_origin; Math::Vector3f m_dir; + mutable Math::Vector2f m_baryPos; }; }