Fix #139753: Discontinuity in mesh tangent without UV map
when there is no uv, we call the function `map_to_sphere()` to create temporary uv for computing the tangent. It could happen that a triangle has vertices with the u coordinates going across the line where u wraps from 1 to 0. In this case, just computing the difference of the u coordinates results in the wrong triangle area. To fix this problem, we compute distance in toroidal (wrap around) space. This is safe for coordinates generated by `map_to_sphere()` function, because it is not supposed to map the positions of a triangle to u coordinates that span larger than 0.5. Pull Request: https://projects.blender.org/blender/blender/pulls/139880
This commit is contained in:
parent
1dfe8047d3
commit
ee578cc738
@ -67,7 +67,7 @@ struct MikkMeshWrapper {
|
||||
{
|
||||
/* TODO: Check whether introducing a template boolean in order to
|
||||
* turn this into a constexpr is worth it. */
|
||||
if (uv != nullptr) {
|
||||
if (has_uv()) {
|
||||
const int corner_index = CornerIndex(face_num, vert_num);
|
||||
const float2 tfuv = uv[corner_index];
|
||||
return mikk::float3(tfuv.x, tfuv.y, 1.0f);
|
||||
@ -101,6 +101,11 @@ struct MikkMeshWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
bool has_uv() const
|
||||
{
|
||||
return uv != nullptr;
|
||||
}
|
||||
|
||||
const Mesh *mesh;
|
||||
|
||||
const float3 *normal;
|
||||
|
@ -253,6 +253,11 @@ template<typename Mesh> class Mikktspace {
|
||||
return mesh.GetTexCoord(f, v);
|
||||
}
|
||||
|
||||
bool has_uv() const
|
||||
{
|
||||
return mesh.has_uv();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -522,9 +527,16 @@ template<typename Mesh> class Mikktspace {
|
||||
const float3 t2 = getTexCoord(triangle.vertices[1]);
|
||||
const float3 t3 = getTexCoord(triangle.vertices[2]);
|
||||
|
||||
const float t21x = t2.x - t1.x;
|
||||
float t21x = t2.x - t1.x;
|
||||
float t31x = t3.x - t1.x;
|
||||
if (!has_uv()) {
|
||||
/* Compute edge length in toroidal space, since the u generated by `map_to_sphere()` might
|
||||
* go cross the seam. */
|
||||
t21x -= floorf(t21x + 0.5f);
|
||||
t31x -= floorf(t31x + 0.5f);
|
||||
}
|
||||
|
||||
const float t21y = t2.y - t1.y;
|
||||
const float t31x = t3.x - t1.x;
|
||||
const float t31y = t3.y - t1.y;
|
||||
const float3 d1 = v2 - v1, d2 = v3 - v1;
|
||||
|
||||
|
@ -95,7 +95,7 @@ struct SGLSLEditMeshToTangent {
|
||||
mikk::float3 GetTexCoord(const uint face_num, const uint vert_index)
|
||||
{
|
||||
const BMLoop *l = GetLoop(face_num, vert_index);
|
||||
if (cd_loop_uv_offset != -1) {
|
||||
if (has_uv()) {
|
||||
const float *uv = (const float *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
|
||||
return mikk::float3(uv[0], uv[1], 1.0f);
|
||||
}
|
||||
@ -130,6 +130,11 @@ struct SGLSLEditMeshToTangent {
|
||||
copy_v4_fl4(p_res, T.x, T.y, T.z, orientation ? 1.0f : -1.0f);
|
||||
}
|
||||
|
||||
bool has_uv()
|
||||
{
|
||||
return cd_loop_uv_offset != -1;
|
||||
}
|
||||
|
||||
Span<float3> face_normals;
|
||||
Span<float3> corner_normals;
|
||||
Span<std::array<BMLoop *, 3>> looptris;
|
||||
|
@ -70,6 +70,11 @@ struct BKEMeshToTangent {
|
||||
copy_v4_fl4(p_res, T.x, T.y, T.z, orientation ? 1.0f : -1.0f);
|
||||
}
|
||||
|
||||
bool has_uv() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
OffsetIndices<int> faces; /* faces */
|
||||
const int *corner_verts; /* faces vertices */
|
||||
const float (*positions)[3]; /* vertices */
|
||||
@ -227,7 +232,7 @@ struct SGLSLMeshToTangent {
|
||||
int3 tri;
|
||||
int face_index;
|
||||
uint loop_index = GetLoop(face_num, vert_num, tri, face_index);
|
||||
if (mloopuv != nullptr) {
|
||||
if (has_uv()) {
|
||||
const float2 &uv = mloopuv[loop_index];
|
||||
return mikk::float3(uv[0], uv[1], 1.0f);
|
||||
}
|
||||
@ -281,6 +286,11 @@ struct SGLSLMeshToTangent {
|
||||
copy_v4_fl4(tangent[loop_index], T.x, T.y, T.z, orientation ? 1.0f : -1.0f);
|
||||
}
|
||||
|
||||
bool has_uv() const
|
||||
{
|
||||
return mloopuv != nullptr;
|
||||
}
|
||||
|
||||
Span<float3> face_normals;
|
||||
Span<float3> corner_normals;
|
||||
const int3 *corner_tris;
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cd07487f8bb71a4199fb15cf994599317670ca806757fdae24c00c85a26d3be2
|
||||
size 28659
|
||||
oid sha256:7fa3ab720f94fa70de22f70f9e87bd74b8cc06bff20a82352b53ee24d02e14d8
|
||||
size 28195
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4a3a786cd629cbd7074a40c5ece486d6dccd031e8cafdf41ad5bd62f9c1afb1a
|
||||
size 20981
|
||||
oid sha256:e69131fc75964401791a7a13a29d50a44e04699f29f8ff23d827ddbd75899d3a
|
||||
size 20489
|
||||
|
@ -43,8 +43,6 @@ BLOCKLIST = [
|
||||
]
|
||||
|
||||
BLOCKLIST_METAL = [
|
||||
# Blocked due to difference in tangent space calculation (to be fixed).
|
||||
"tangent_no_uv.blend",
|
||||
# Blocked due to difference in volume lightprobe bakes (to be fixed).
|
||||
"clamp_.*.blend",
|
||||
"shadow_all_max_bounces.blend",
|
||||
|
Loading…
x
Reference in New Issue
Block a user