74 lines
2.3 KiB
C++
74 lines
2.3 KiB
C++
#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<Sample> 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 =
|
|
[&]<typename Type>(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
|
|
};
|
|
}
|
|
|