#include "HitTest.h" float CrossZ(const Vector3& p0, const Vector3& p1, const Vector3& point) { return (p1.x - p0.x) * (point.y - p0.y) - (p1.y - p0.y) * (point.x - p0.x); } std::optional TriangleHitTest(const Vector3& fragPos, const VertexOut& v0, const VertexOut& v1, const VertexOut& v2) { Vector3 weights; weights.x = CrossZ(v2.position, v1.position, fragPos); if ( weights.x > 0 ) return std::nullopt; weights.y = CrossZ(v0.position, v2.position, fragPos); if ( weights.y > 0 ) return std::nullopt; weights.z = CrossZ(v1.position, v0.position, fragPos); if ( weights.z > 0 ) return std::nullopt; const float totalWeight{ weights.x + weights.y + weights.z }; const float invTotalWeight{ 1.0f / totalWeight }; const Vector3 normWeights{ weights.x * invTotalWeight, weights.y * invTotalWeight, weights.z * invTotalWeight }; const float depth = 1 / (normWeights.x / v0.position.w + normWeights.y / v1.position.w + normWeights.z / v2.position.w); const Vector2 uv = v0.uv * depth * normWeights.x / v0.position.w + v1.uv * depth * normWeights.y / v1.position.w + v2.uv * depth * normWeights.z / v2.position.w; const float interpolatedDepth = 1 / (normWeights.x / v0.position.w + normWeights.y / v1.position.w + normWeights.z / v2.position.w); auto interpolate = [&](const Type& val0, const Type& val1, const Type& val2) -> Type { return (val0 / v0.position.w * normWeights.x + val1 / v1.position.w * normWeights.y + val2 / v2.position.w * normWeights.z) * interpolatedDepth; }; //Invert the normal const Vector3 normal = interpolate(v0.normal, v1.normal, v2.normal).Normalized(); const Vector3 tangent = interpolate(v0.tangent, v1.tangent, v2.tangent).Normalized(); const Vector3 viewDir = interpolate(v0.viewDir, v1.viewDir, v2.viewDir).Normalized(); return Sample{ .uv = uv, .normal = normal, .tangent = tangent, .viewDirection = viewDir, .depth = depth, .weight = normWeights, .mesh = v0.mesh }; }